我有很多用户/项目/时间戳数据。我想知道所有用户首先消耗了哪些项目,第二个等等。
我的问题是:如果我的数据框已经按时间排序(降序),那么它是否会默认通过groupby
进程排序?并且,即使用户没有消耗两个项目,我怎样才能拉出任何用户消耗的前两个项目?
import pandas as pd
df = pd.DataFrame({'item_id': ['b', 'b', 'a', 'c', 'a', 'b'], 'user_id': [1,2,1,1,3,1], 'time': range(6)})
print df
pd.get_dummies(df['item_id'])
gp = df.groupby('user_id').head()
print gp
# Return item_id of first one installed in each case ??
这给出了:
item_id time user_id
0 b 0 1
1 b 1 2
2 a 2 1
3 c 3 1
4 a 4 3
5 b 5 1
item_id time user_id
user_id
1 0 b 0 1
2 a 2 1
3 c 3 1
5 b 5 1
2 1 b 1 2
3 4 a 4 3
现在,我需要提取前两个item_id值,类似这样(但保留user_id列并不重要):
user_id order item_id
1 0 b
1 1 a
2 0 b
3 0 a
答案 0 :(得分:4)
这是一个黑客:
In [75]: def nth_order(x, n):
....: xn = x[:n]
....: return xn.join(Series(arange(len(xn)), name='order', index=xn.index))
....:
In [76]: df.groupby('user_id').apply(lambda x: nth_order(x, 2))
Out[76]:
item_id time user_id order
user_id
1 0 b 0 1 0
2 a 2 1 1
2 1 b 1 2 0
3 4 a 4 3 0
请注意,您不能只使用n
,因为您可能有一个len(group) < 2
组,因此
len(x[:n]) != n
在每种情况下(根据您的问题)。
这是pandas中这种特殊切片的一个特性:如果切片在这里传递结尾,你将获得每一行(并且可能没有n
行),而{{3} ,那不是真的。也就是说,如果您尝试切片超出数组的末尾,则会引发异常。
答案 1 :(得分:2)
您可以直接使用获得最高n
结果的head来执行此操作:
In [11]: g = df.groupby('user_id')
In [12]: g.head(2)
Out[12]:
item_id time user_id
user_id
1 0 b 0 1
2 a 2 1
2 1 b 1 2
3 4 a 4 3
从0.13 IIRC开始,这比任何基于应用的解决方案头更快 (调用头曾经是.apply(lambda x: x.head())
的一个突破。
该实现使用cumcount
,因此在精神上与PhilipCloud的解决方案类似。