Pandas:按第一次和最后一次出现填充每一行
Posted
技术标签:
【中文标题】Pandas:按第一次和最后一次出现填充每一行【英文标题】:Pandas: Fill every row by its first and last occurrence 【发布时间】:2019-12-07 18:42:42 【问题描述】:我的数据包括发票和客户。 一位客户可以有多张发票。一张发票始终属于一位客户。发票每天更新(报告日期)。
我的目标是以天为单位计算客户的年龄(请参阅“以天为单位的年龄”列)。为了实现这一点,我采用客户报告日期的第一次出现并计算与报告日期最后一次出现的差异。
例如客户 1 出现在 08-14 到 08-15 之间。因此他/她只有 1 天大。
Report Date Invoice No Customer No Amount Age in Days
2018-08-14 A 1 50$ 1
2018-08-14 B 1 100$ 1
2018-08-14 C 2 75$ 2
2018-08-15 A 1 20$ 1
2018-08-15 B 1 45$ 1
2018-08-15 C 2 70$ 2
2018-08-16 C 2 40$ 1
2018-08-16 D 3 100$ 0
2018-08-16 E 3 60$ 0
我解决了这个问题,但是效率很低,而且花费的时间太长。我的数据包含 2600 万行。下面我只计算了一位客户的年龄。
# List every customer no
customerNo = df["Customer No"].unique()
customer_age = []
# Testing for one specific customer
testCustomer = df.loc[df["Customer No"] == customerNo[0]]
testCustomer = testCustomer.sort_values(by="Report Date", ascending=True)
first_occur = testCustomer.iloc[0]['Report Date']
last_occur = testCustomer.iloc[-1]['Report Date']
age = (last_occur - first_occur).days
customer_age.extend([age] * len(testCustomer))
testCustomer.loc[:,'Customer Age']=customer_age
有没有更好的方法来解决这个问题?
【问题讨论】:
【参考方案1】:将groupby.transform
与first
和last
聚合一起使用:
grps = df.groupby('Customer No')['Report Date']
df['Age in Days'] = (grps.transform('last') - grps.transform('first')).dt.days
[出]
Report Date Invoice No Customer No Amount Age in Days
0 2018-08-14 A 1 50$ 1
1 2018-08-14 B 1 100$ 1
2 2018-08-14 C 2 75$ 2
3 2018-08-15 A 1 20$ 1
4 2018-08-15 B 1 45$ 1
5 2018-08-15 C 2 70$ 2
6 2018-08-16 C 2 40$ 2
7 2018-08-16 D 3 100$ 0
8 2018-08-16 E 3 60$ 0
【讨论】:
非常感谢!这工作得很好。在 10 秒内计算了 2600 万行!! @Azrion 不错 :)【参考方案2】:如果您需要每个客户一个值,表明其年龄,您可以使用分组依据(非常常见):
grpd = my_df.groupby('Customer No')['Report Date'].agg([min, max]).reset_index()
grpd['days_diff'] = (grpd['max'] - grpd['min']).dt.days
【讨论】:
以上是关于Pandas:按第一次和最后一次出现填充每一行的主要内容,如果未能解决你的问题,请参考以下文章
2021-09-23:编写一个程序,通过填充空格来解决数独问题。数独的解法需遵循如下规则:数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分隔的(