对每一行应用一个函数,其中函数使用 DataFrame 的所有先前行
Posted
技术标签:
【中文标题】对每一行应用一个函数,其中函数使用 DataFrame 的所有先前行【英文标题】:Apply a function to each row, where the function uses all previous rows of the DataFrame 【发布时间】:2020-08-19 21:06:25 【问题描述】:我有一个类似于以下格式的 DataFrame:
date customer_id transaction_id amount fraud
2020-01-01 1 10 25 0
2020-01-01 2 11 14 1
2020-01-02 1 12 48 1
2020-01-02 2 13 12 1
2020-01-02 2 14 48 1
2020-01-03 1 15 30 0
按date
、customer_id
、transaction_id
排序。
我现在想创建两个新列,fraud_count
,它将显示该客户在当前日期(但不包括当前日期)进行的欺诈 (fraud == 1
) 交易的数量。 fraud_sum
会一样,但是是交易金额的累计,而不是计数。
date customer_id transaction_id amount fraud fraud_count fraud_sum
2020-01-01 1 10 25 0 0 0
2020-01-01 2 11 14 1 0 0
2020-01-02 1 12 48 1 0 0
2020-01-02 2 13 12 1 1 14
2020-01-02 2 14 41 1 1 14
2020-01-03 1 15 30 0 1 48
2020-01-03 2 16 88 0 3 67
我怎样才能做到这一点?是否可以创建一个查看整个 DataFrame 或当前行之前的所有行的函数,然后使用 pd.DataFrame.apply()
将其应用于每一行?
【问题讨论】:
过滤出日期为 customer_id 和aggregate
上应用 groupby 并在列 fraud
和 amount
上使用函数 cumsum
。
你的价值观正确吗?根据您的逻辑,第 3 行的数量应该是 25 而不是 0?
否,因为它应该只计算以前的值 fraud == 1
【参考方案1】:
我相信您首先需要过滤fraud
列的1
值,然后通过GroupBy.agg
聚合计数和sum
,然后创建每个customer_id
的累积总和,并添加与之前不匹配的下几天:
df1 = df[df['fraud'].eq(1)].copy()
df1 = (df1.groupby(['customer_id', 'date'])
.agg(fraud_count=('amount','size'),
fraud_sum=('amount','sum'))
.reset_index())
cols = ['fraud_sum','fraud_count']
df1[cols] = df1.groupby('customer_id')[cols].cumsum()
df1['date'] += pd.Timedelta(1, 'day')
最后使用DataFrame.merge
替换缺失值:
df = df.merge(df1[['fraud_count','fraud_sum', 'date','customer_id']],
on=['date','customer_id'], how='left')
df[cols] = df[cols].fillna(0).astype(int)
print (df)
date customer_id transaction_id amount fraud fraud_count \
0 2020-01-01 1 10 25 0 0
1 2020-01-01 2 11 14 1 0
2 2020-01-02 1 12 48 1 0
3 2020-01-02 2 13 12 1 1
4 2020-01-02 2 14 41 1 1
5 2020-01-03 1 15 30 0 1
6 2020-01-03 2 16 88 0 3
fraud_sum
0 0
1 0
2 0
3 14
4 14
5 48
6 67
【讨论】:
我的和你的差不多。但还没有完成。所以,投票给你并删除我的。以上是关于对每一行应用一个函数,其中函数使用 DataFrame 的所有先前行的主要内容,如果未能解决你的问题,请参考以下文章