我面临着一个复杂的问题。 我有第一个数据帧,其中有客户(注意ClientID不是唯一的,您可以将相同的ClientID与不同的TestDate关联):
df1:
ClientID TestDate
1A 2019-12-24
1B 2019-08-26
1B 2020-01-12
我有另一个“操作”数据框,指示日期和涉及的客户机
df2:
LineNumber ClientID Date Amount
1 1A 2020-01-12 50
2 1A 2019-09-24 15
3 1A 2019-12-25 20
4 1A 2018-12-30 30
5 1B 2018-12-30 60
6 1B 2019-12-12 40
我想在df1中添加一列,其中包含平均行数和行数,但只取df2行,其中日期<;测试日期
例如,对于客户机1A,我将只获取行号2和4(因为行号1和3的日期晚于TestDate),然后获取df1的以下输出:
预期df1:
ClientID TestDate NumberOp MeanOp
1A 2019-12-24 2 22.5
1B 2019-08-26 1 60
1B 2020-01-12 2 50
注意:对于1B客户机的第一行,因为TestDate是2019-08-26
,所以只看到一个操作(行号6操作是在2019-12-12
中完成的,所以在TestDate之后,所以我不考虑它)
我已经有了代码,但是我必须在我的df1
上使用iterrows
,这需要花费一些时间:
当前代码(有效但很长):
for index, row in df1.iterrows():
id = row['ClientID']
date = row['TestDate']
df2_known = df2.loc[df2['ClientID'] == id]
df2_known = df2_known.loc[df2_known['Date'] < date]
df1.loc[index, 'NumberOp'] = df2_known.shape[0]
df1.loc[index, 'MeanOp'] = df2_known['Amount'].mean()
我想到了使用聚合,以及像mean
和count
这样的命令,但是我必须按日期为每一行筛选这一事实是一个我无法理解的巨大问题。
非常感谢您的帮助
编辑:剩余问题:
答案编辑中给出的修复(“如果您想保留缺少的df2匹配键”)与我的问题不对应
事实上,如果df2中没有任何操作可用于计算平均值和计数,我希望避免丢失df1的等效行。 我将用一个例子向您展示这个问题:
df = df2.merge(df1, on=['ClientID'], how='right')
print(df[df['ClientID'] == '5C'])
Output :
ClientID TestDate Date Amount
5C 2019-12-12 2020-01-12 50
如果我按照答案中给出的方式执行groupby
和transform
,我的输出将不会有任何带有CliendID == '5C'
的行,因为Date < TestDate
和Date is null
永远不会发生,所以执行df = df[(df['Date']<df['TestDate']) | (df['Date'].isnull())]
时,行会丢失。我个人希望在我的最终输出中有一行CliendID == '5C'
,看起来是这样的:
ClientID TestDate NumberOp MeanOp
5C 2019-12-12 0 NaN
您可以合并和转换:
输出:
编辑:如果要保留
df2
缺少的匹配键:例如:
更新:根据帖子上的编辑,如果要按
(Client_ID, TestDate)
对其进行分组:输出:
相关问题 更多 >
编程相关推荐