pandas Dataframe groupby以获取限制

tquggr8v  于 2023-02-27  发布在  其他
关注(0)|答案(3)|浏览(131)

我有一个新的代码,我试图写一个数据框得到过滤/编辑,以获得"stints"为每个人。使用下面的数据框作为一个例子,我基本上是试图得到每个人的开始/结束日期为给定的位置。通常我可以开始对我自己,但我被难倒了,如何处理这个问题,所以如果有人有想法,我会非常感谢它。
| | 人|位置|日期|
| - ------|- ------|- ------|- ------|
| 无|汤姆|A类|2021年1月1日|
| 1个|汤姆|A类|2021年1月2日|
| 第二章|汤姆|A类|2021年1月3日|
| 三个|汤姆|乙|2021年1月4日|
| 四个|汤姆|乙|2021年1月5日|
| 五个|汤姆|乙|2021年1月6日|
| 六个|汤姆|A类|2021年1月7日|
| 七|汤姆|A类|2021年1月8日|
| 八个|汤姆|A类|2021年1月9日|
| 九|汤姆|C级|2021年1月10日|
| 十个|汤姆|C级|2021年1月11日|
| 十一|汤姆|A类|2021年1月12日|
| 十二|汤姆|A类|二○二一年一月十三日|
| 十三|汤姆|乙|二○二一年一月十四日|
| 十四|汤姆|乙|二○二一年一月十五日|
| 十五|马克|A类|2021年1月1日|
| 十六|马克|A类|2021年1月2日|
| 十七|马克|乙|2021年1月3日|
| 十八|马克|乙|2021年1月4日|
| 十九|马克|A类|2021年1月5日|
| 二十个|马克|A类|2021年1月6日|
| 二十一|马克|C级|2021年1月7日|
| 二十二|马克|C级|2021年1月8日|
| 二十三|马克|C级|2021年1月9日|
| 二十四|马克|C级|2021年1月10日|
| 二十五|马克|A类|2021年1月11日|
| 二十六|马克|A类|2021年1月12日|
| 二十七|马克|乙|二○二一年一月十三日|
| 二十八|马克|乙|二○二一年一月十四日|
| 二十九|马克|乙|二○二一年一月十五日|
预期成果:
| | 人|位置|统计编号|开始日期|结束日期|
| - ------|- ------|- ------|- ------|- ------|- ------|
| 无|汤姆|A类|1个|2021年1月1日|2021年1月3日|
| 1个|汤姆|乙|第二章|2021年1月4日|2021年1月6日|
| 第二章|汤姆|A类|三个|2021年1月7日|2021年1月9日|
| 三个|汤姆|C级|四个|2021年1月10日|2021年1月11日|
| 四个|汤姆|A类|五个|2021年1月12日|二○二一年一月十三日|
| 五个|汤姆|乙|六个|二○二一年一月十四日|二○二一年一月十五日|
| 六个|马克|A类|1个|2021年1月1日|2021年1月2日|
| 七|马克|乙|第二章|2021年1月3日|2021年1月4日|
| 八个|马克|A类|三个|2021年1月5日|2021年1月6日|
| 九|马克|C级|四个|2021年1月7日|2021年1月10日|
| 十个|马克|A类|五个|2021年1月11日|2021年1月12日|
| 十一|马克|乙|六个|二○二一年一月十三日|二○二一年一月十五日|

wwtsj6pe

wwtsj6pe1#

IMO,一个干净的方法是使用groupby + agg,这使得设置自定义聚合器很容易,比apply更快:

df['Date'] = pd.to_datetime(df['Date'])

group = df['Location'].ne(df['Location'].shift()).cumsum()

df2 = (
 df.groupby(['Person', group], as_index=False)
   .agg(Location=('Location', 'first'),
        # line below is a dummy function to set a column placeholder
        # uncomment it you want the columns in order
        #StintNum=('Location', lambda x: float('NaN')),
        Start_Date=('Date', 'min'), 
        End_Date=('Date', 'max'),
       )
)

df2['StintNum'] = df2.groupby('Person').cumcount().add(1)

输出:

Person Location  StintNum Start_Date   End_Date
0    Mark        A         1 2021-01-01 2021-01-02
1    Mark        B         2 2021-01-03 2021-01-04
2    Mark        A         3 2021-01-05 2021-01-06
3    Mark        C         4 2021-01-07 2021-01-10
4    Mark        A         5 2021-01-11 2021-01-12
5    Mark        B         6 2021-01-13 2021-01-15
6     Tom        A         1 2021-01-01 2021-01-03
7     Tom        B         2 2021-01-04 2021-01-06
8     Tom        A         3 2021-01-07 2021-01-09
9     Tom        C         4 2021-01-10 2021-01-11
10    Tom        A         5 2021-01-12 2021-01-13
11    Tom        B         6 2021-01-14 2021-01-15
xxls0lw8

xxls0lw82#

试试这个:

df['Date'] = pd.to_datetime(df['Date'])
new_df = df.groupby([df['Person'], df['Location'].ne(df['Location'].shift(1)).cumsum()], sort=False).apply(lambda x: pd.Series([x['Date'].min(), x['Date'].max()], index=['Start_Date','End_Date'])).reset_index()
new_df['StintNum'] = new_df.groupby('Person').cumcount().add(1)

输出:

>>> new_df
   Person  Location Start_Date   End_Date  StintNum
0     Tom         1 2021-01-01 2021-01-03         1
1     Tom         2 2021-01-04 2021-01-06         2
2     Tom         3 2021-01-07 2021-01-09         3
3     Tom         4 2021-01-10 2021-01-11         4
4     Tom         5 2021-01-12 2021-01-13         5
5     Tom         6 2021-01-14 2021-01-15         6
6    Mark         7 2021-01-01 2021-01-02         1
7    Mark         8 2021-01-03 2021-01-04         2
8    Mark         9 2021-01-05 2021-01-06         3
9    Mark        10 2021-01-07 2021-01-10         4
10   Mark        11 2021-01-11 2021-01-12         5
11   Mark        12 2021-01-13 2021-01-15         6
llew8vvj

llew8vvj3#

def function1(dd:pd.DataFrame):
    dd1=dd.groupby(["Person","Location"],as_index=False).agg(StintNum=("col1","first"),Start_Date=("Date",min),End_Date=("Date",max))
    return dd1

col1=df1.groupby("Person",group_keys=False).apply(lambda dd:dd.Location.ne(dd.Location.shift()).cumsum())

df1.assign(col1=col1).groupby(["Person","col1"],sort=False).apply(function1).reset_index(drop=True)

输出:

Person Location  StintNum Start_Date   End_Date
0     Tom        A         1   1/1/2021   1/3/2021
1     Tom        B         2   1/4/2021   1/6/2021
2     Tom        A         3   1/7/2021   1/9/2021
3     Tom        C         4  1/10/2021  1/11/2021
4     Tom        A         5  1/12/2021  1/13/2021
5     Tom        B         6  1/14/2021  1/15/2021
6    Mark        A         1   1/1/2021   1/2/2021
7    Mark        B         2   1/3/2021   1/4/2021
8    Mark        A         3   1/5/2021   1/6/2021
9    Mark        C         4  1/10/2021   1/9/2021
10   Mark        A         5  1/11/2021  1/12/2021
11   Mark        B         6  1/13/2021  1/15/2021

相关问题