Python 使用另一个数据集的cumsum对具有不同聚集的不同列进行分组

Python 使用另一个数据集的cumsum对具有不同聚集的不同列进行分组,python,pandas,pandas-groupby,cumsum,Python,Pandas,Pandas Groupby,Cumsum,我有一个按日期和时间排序的数据框: df1: df2: 我想在id上附加这两个dfs,并想将df2作为输出更新为: ID Date A_sum A_count B_sum B_count A_last B_last abc 02/jan 50 #26+10+14 4 #2+2 48 4 14 13 xyz 02/jan 118 #54+26+18+20 6 #3+3

我有一个按日期和时间排序的数据框: df1:

df2:

我想在id上附加这两个dfs,并想将df2作为输出更新为:

ID    Date     A_sum             A_count    B_sum   B_count  A_last  B_last  
abc   02/jan  50 #26+10+14        4 #2+2     48       4      14      13
xyz   02/jan  118 #54+26+18+20    6 #3+3    100       6      20      16

因此,它从df1中获取列的上一个值,并将其添加到df2中。您可以将两个df合并,然后使用
groupby

cols = df1.columns
df1 = df1[['ID','Date','A_sum', 'B_sum']]
df2 = df2.drop('Time', 1)
df1.columns = df2.columns
merged_df  = pd.concat([df1, df2]).groupby(['ID']).agg({'A' : [sum , 'count', 'last'], 'B' : [sum , 'count', 'last'], 'Date': 'last'})
merged_df.columns = merged_df.columns.map('_'.join)
输出:

     A_sum  A_count  A_last  B_sum  B_count  B_last Date_last
ID                                                           
abc     50        3      14     48        3      13    02/jan
xyz    118        4      20    100        4      16    02/jan
狭长的路

>>> import pandas as pd
>>> from io import StringIO
>>>
>>> df1 = pd.read_csv(StringIO("""ID    Date     A_sum  A_count   B_sum   B_count  A_last  B_last
... abc   01/jan    26       2        25       2       0      0
... xyz   01/jan    54       3        45       3       4      6"""), sep="\s+")
>>>
>>>
>>> df2 = pd.read_csv(StringIO("""ID     Date     Time      A         B
... abc   02/jan     11       10        10
... abc   02/jan     12       14        13
... xyz   02/jan      1       26        24
... xyz   02/jan      2       18        15
... xyz   02/jan      3       20        16"""), sep="\s+")
>>>
>>>
>>>
>>> df2["A_sum"]   = df2.groupby("ID")["A"].transform("sum")
>>> df2["A_count"] = df2.groupby("ID")["A"].transform("count")
>>> df2["A_last"]  = df2.groupby("ID")["A"].transform("last")
>>>
>>> df2["B_sum"]   = df2.groupby("ID")["B"].transform("sum")
>>> df2["B_count"] = df2.groupby("ID")["B"].transform("count")
>>> df2["B_last"]  = df2.groupby("ID")["B"].transform("last")
>>>
>>> del df2["Time"]
>>> del df2["A"]
>>> del df2["B"]
>>>
>>> df2 = df2.groupby("ID").apply(lambda x: x.iloc[-1])
>>>
>>> df3 = pd.concat([df1, df2])
>>>
>>> df3.groupby('ID').agg({"Date": 'last', 'A_sum': 'sum', 'B_sum' : 'sum', 'A_count': 'sum', 'B_count': 'sum', 'A_last': 'last', 'B_last': 'last'})
       Date  A_sum  B_sum  A_count  B_count  A_last  B_last
ID
abc  02/jan     50     48        4        4      14      13
xyz  02/jan    118    100        6        6      20      16
您可以使用和将
df2
转换为与
df1
相同的布局,然后将结果附加到
df1
,然后进行另一轮
groupby()
和聚合,如下所示:

df3 = (df2.groupby(['ID', 'Date'], as_index=False, sort=False)
          .agg(A_sum=('A', 'sum'), A_count=('A', 'count'), 
               B_sum=('B', 'sum'), B_count=('A', 'count'), 
               A_last=('A', 'last'), B_last=('B', 'last'))
      )

df_out = (df1.append(df3)
             .groupby('ID', as_index=False)
             .agg({'Date': 'last', 
                   'A_sum': 'sum', 'A_count': 'sum', 
                   'B_sum': 'sum', 'B_count': 'sum', 
                   'A_last': 'last', 'B_last': 'last'})
         )
结果:

print(df_out)


    ID    Date  A_sum  A_count  B_sum  B_count  A_last  B_last
0  abc  02/jan     50        4     48        4      14      13
1  xyz  02/jan    118        6    100        6      20      16
使用:

仅从
df1
中筛选列求和:

df33 = df1.filter(regex='ID|_sum|count').set_index('ID')
print (df33)
     A_sum  A_count  B_sum  B_count
ID                                 
abc     26        2     25        2
xyz     54        3     45        3
如有必要,将
sum
组合在一起,并指定缺少的
日期

df = pd.concat([df3, df33]).sum(level=0).astype(int).assign(Date = df3['Date']).set_index('Date', append=True).reset_index()
print (df)
    ID    Date  A_sum  A_count  B_sum  B_count  A_last  B_last
0  abc  02/jan     50        4     48        4      14      13
1  xyz  02/jan    118        6    100        6      20      16

日期不重要?不,它不重要…一个计数应该是2+2=4,3+3=6i有40列,它给出了语法错误,就像我在cols中用于i一样:df3=(df2.groupby(['ID','Date','as'u index=False)。agg(i+''u Num'=(i,'sum'),i+'u denom'=(i,'count'),i+'u last'=(i,'last'))final=(df1.append(df3)。groupby('ID','as'u index=False)。agg({i+''Num':'sum',i+'denom':'sum',i+'u Last':'Last'})我是专栏作家name@naina如果要在循环中对所有列使用它,则不能使用此语法。因为对于命名聚合,它是
=
左侧的变量名,而不是字符串。此外,您将获得难以使用的离散聚合结果。@naina在这种情况下,您可能需要返回到solut像另一个解决方案一样一个接一个地定义列。对不起,我现在有一些紧急任务。您可能需要向另一个解决方案海报寻求帮助,如何修改他/她的解决方案以满足您的需要。我无法理解这行..df33=df1.filter(regex='ID | | u sum | count')。set_index('ID'))实际名称是A_Num、A_denom、B_Num、B_denom@naina-它仅过滤具有
\u sum
\u count
ID
susbtrings@naina-因为只有这些列对sum to
df3
df33=df2.filter(regex='ID | | | | | | | u denom')很重要。设置索引('ID'))请使用我的代码,对吗?@naina-是的,没错。如果这是对您的问题的澄清,请编辑问题本身并将其添加到那里。如果这是解决方案,请在此处明确说明。请使用问题上的编辑链接添加其他信息。发布答案按钮应仅用于完整回答问题斯蒂昂-
for i in cols:
   df3 = (df2.groupby(['ID', 'Date'], as_index=False).agg(i+'_Num'=(i, 'sum'),i+'_denom'=(i,'count'),i+'_last'=(i, 'last'))
   final = (df1.append(df3).groupby('ID', as_index=False).agg({i+'_Num':'sum',i+'_denom':'sum', i+'_Last': 'last'}))
But it is not working
#https://stackoverflow.com/a/67800033/2901002
cols = ['A','B']

df11 = df2.groupby(['ID','Date'])[cols].agg(['sum','count'])
df11.columns = df11.columns.map(lambda x: f'{x[0]}_{x[1]}')

df22 = df2.groupby(['ID','Date'])[cols].last().add_suffix('_last')

df3 = pd.concat([df11, df22], axis=1).reset_index(level=1)
print (df3)
       Date  A_sum  A_count  B_sum  B_count  A_last  B_last
ID                                                         
abc  02/jan     24        2     23        2      14      13
xyz  02/jan     64        3     55        3      20      16
df33 = df1.filter(regex='ID|_sum|count').set_index('ID')
print (df33)
     A_sum  A_count  B_sum  B_count
ID                                 
abc     26        2     25        2
xyz     54        3     45        3
df = pd.concat([df3, df33]).sum(level=0).astype(int).assign(Date = df3['Date']).set_index('Date', append=True).reset_index()
print (df)
    ID    Date  A_sum  A_count  B_sum  B_count  A_last  B_last
0  abc  02/jan     50        4     48        4      14      13
1  xyz  02/jan    118        6    100        6      20      16