以下数据框显示了几年中两家商店(shop_id=11
,shop_id=15
)的月收入:
data = { 'shop_id' : [ 11, 15, 15, 15, 11, 11 ],
'month' : [ 1, 1, 2, 3, 2, 3 ],
'year' : [ 2011, 2015, 2015, 2015, 2014, 2014 ],
'revenue' : [11000, 5000, 4500, 5500, 10000, 8000]
}
df = pd.DataFrame(data)
df = df[['shop_id', 'month', 'year', 'revenue']]
display(df)
您会注意到shop_id=11
在2011年(1月)只有一个条目,而shop_id=15
在2015年(1月,2月和3月)只有几个条目。不过,有趣的是,第一家商店在2014年还有更多条目:
我正在尝试优化自定义功能(与.apply()
一起使用),以创建名为diff_revenue
的新功能:此功能显示了每个商店的上个月收入变化:
我想对如何生成diff_revenue
中的某些值提供一些解释:
shop_id=11
的先前信息; shop_id=15
没有先前的信息; 我不是熊猫专家,并且想知道熊猫神是否知道更好的方法。我必须使用的DataFrame很大(+ 1M观察),而我目前的方法太慢了。我正在寻找一种更快的替代方法,或者可能是更具可读性的方法。
答案 0 :(得分:2)
您或多或少希望在'Revenue'
列上使用Series.diff
,但需要做一些其他事情:
groupby
上执行'shop_id'
以进行组级操作在代码方面:
# sort the values so they're in order when we perform a groupby
df = df.sort_values(by=['year', 'month'])
# perform a groupby on 'shop_id' and get the row-wise difference within each group
df['diff_revenue'] = df.groupby('shop_id')['revenue'].diff()
# fill NA as zero (no previous info), take absolute value, convert float -> int
df['diff_revenue'] = df['diff_revenue'].fillna(0).abs().astype('int')
# revert to original order
df = df.sort_index()
结果输出:
shop_id month year revenue diff_revenue
0 11 1 2011 11000 0
1 15 1 2015 5000 0
2 15 2 2015 4500 500
3 15 3 2015 5500 1000
4 11 2 2014 10000 1000
5 11 3 2014 8000 2000
修改
不太直接的解决方案,但性能可能更高:
# sort the values so they're chronological order by shop_id
df = df.sort_values(by=['shop_id', 'year', 'month'])
# take the row-wise difference ignoring changes in shop_id
df['diff_revenue'] = df['revenue'].diff()
# zero out locations where shop_id changes (no previous info)
df.loc[df['shop_id'] != df['shop_id'].shift(), 'diff_revenue'] = 0
# Take the absolute value, convert float -> int
df['diff_revenue'] = df['diff_revenue'].abs().astype('int')
# revert to original order
df = df.sort_index()