【发布时间】:2020-11-30 07:15:06
【问题描述】:
假设我有这个简单的数据框-
dic = {'firstname':['Steve','Steve','Steve','Steve','Steve','Steve'],
'lastname':['Johnson','Johnson','Johnson','Johnson','Johnson',
'Johnson'],
'company':['CHP','CHP','CHP','CHP','CHP','CHP'],
'faveday':['2020-07-13','2020-07-20','2020-07-16','2020-10-14',
'2020-10-28','2020-10-21'],
'paid':[200,300,550,100,900,650]}
df = pd.DataFrame(dic)
df['faveday'] = pd.to_datetime(df['faveday'])
print(df)
带输出-
firstname lastname company faveday paid
0 Steve Johnson CHP 2020-07-13 200
1 Steve Johnson CHP 2020-07-20 300
2 Steve Johnson CHP 2020-07-16 550
3 Steve Johnson CHP 2020-10-14 100
4 Steve Johnson CHP 2020-10-28 900
5 Steve Johnson CHP 2020-10-21 650
我希望能够将具有 faveday 的行保持在另一个 7 天内,但它们的付费列的总和必须大于 1000。
就个人而言,如果我想应用 7 天功能,我会使用-
def sefd (x):
return np.sum((np.abs(x.values-x.values[:,None])/np.timedelta64(1, 'D'))<=7,axis=1)>=2
s=df.groupby(['firstname', 'lastname', 'company'])['faveday'].transform(sefd)
df['seven_days']=s
df = df[s]
del df['seven_days']
这将保留所有条目(所有这些都在另一个按名字、姓氏和公司分组的最喜欢日的 7 天内)。
如果我想应用一个函数来为同一公司的同一个人保留行并且总支付金额 > 1000,我会使用-
df = df[df.groupby(['lastname', 'firstname','company'])['paid'].transform(sum) > 1000]
只是一个简单的变换(求和)函数
这也将保留所有条目(因为所有条目都使用相同的名称和公司,并且总和大于 1000)。
但是,如果我们同时结合这两个函数,实际上不会包含一行。
我想要的输出是-
firstname lastname company faveday paid
0 Steve Johnson CHP 2020-07-13 200
1 Steve Johnson CHP 2020-07-20 300
2 Steve Johnson CHP 2020-07-16 550
4 Steve Johnson CHP 2020-10-28 900
5 Steve Johnson CHP 2020-10-21 650
请注意索引 3 不再有效,因为它仅在索引 5 的 7 天内有效,但如果您将索引 3 付费和索引 5 付费相加,它只会是 750 (
还需要注意的是,由于索引 0、1 和 2 都在 7 天内,因此算作一个求和组 (200 + 300 + 550 > 1000)。
逻辑是,我希望首先查看(基于一组名字、姓氏和公司名称)一个最爱日是否在另一个最爱日的 7 天内。然后在确认这一点后,查看这些 favedays 的付费列的总和是否超过 1000。如果是,请将这些索引保留在数据框中。否则,不要。
给我的建议答案是-
df=df.sort_values(["firstname","lastname","company","faveday"])
def date_difference_from(x,df):
return abs((df.faveday - x).dt.days)
def grouped_dates(grouped_df):
keep = []
for idx, row in grouped_df.iterrows():
within_7 = date_difference_from(row.faveday,grouped_df) <= 7
keep.append(within_7.sum() > 1 and grouped_df[within_7].paid.sum() > 1000)
msk = np.array(keep)
return grouped_df[msk]
df = df.groupby(["firstname","lastname","company"]).apply(grouped_dates).reset_index(drop=True)
print(df)
这对于像这样的小型数据集非常有效,但是当我将其应用于更大的数据集(10,000+ 行)时,会出现一些不一致。
有什么办法可以改进这段代码吗?
【问题讨论】:
-
如果有 3 个日期,每个相隔 4 天(例如 01-01 $500、01-05 $500、01-09 $500),你会怎么做?中间日期组应该在左边和右边吗?日期计数和支付金额?
-
如果可能,是的,包括所有 3 个。重叠很重要,因为它在 7 天的窗口内。
标签: python pandas numpy dataframe time