我想取一个数据框架,如:
USER PACKAGE
0 1 1
1 1 1
2 1 2
3 1 1
4 1 2
5 1 3
6 2 ...
并选择不同的USERS,然后根据不同包的频率创建新列。即最高频率包,第二高等
User First Second Third
0 1 1 2 3
1 2 ...
我可以用for循环来实现这个,但使用数据帧显然很糟糕,我需要在数百万条记录上运行这个,我找不到一个矢量化的方法来实现它。
欢呼在SO你应该尝试它和张贴你自己的代码. 以下是实现该解决方案的一些提示:
- Do
.groupby('USER')
…然后.value_counts()
… - (不需要
.sort()
,因为.value_counts()
默认这样做) - 采取
.head(3)
… - 然后将
pivot
放入表中,在相同的pivot命令中有一个选项可以添加列名'First, Second, Third'
您可以使用SeriesGroupBy.value_counts
默认排序,因此获得前3个索引值,转换为Series
,重构Series.unstack
,rename
列,最后将索引转换为列:
print (df)
USER PACKAGE
0 1 1
1 1 1
2 1 2
3 1 1
4 1 2
5 1 3
6 2 3
df = (df.groupby('USER')['PACKAGE']
.apply(lambda x: pd.Series(x.value_counts().index[:3]))
.unstack()
.rename(columns= dict(enumerate(['First','Second','Third'])))
.reset_index())
print (df)
USER First Second Third
0 1 1.0 2.0 3.0
1 2 3.0 NaN NaN
如果需要所有计数:
df = (df.groupby('USER')['PACKAGE']
.apply(lambda x: pd.Series(x.value_counts().index))
.unstack())
print (df)
0 1 2
USER
1 1.0 2.0 3.0
2 3.0 NaN NaN
编辑:另一个想法,我希望更快的使用:
s = (df.groupby('USER')['PACKAGE']
.apply(lambda x: x.value_counts().index[:3]))
df = (pd.DataFrame(s.tolist(),index=s.index, columns=['First','Second','Third'])
.reset_index())
print (df)
USER First Second Third
0 1 1 2.0 3.0
1 2 3 NaN NaN
我假设计数是用户和包出现的次数
USER =[1,1,1,1,1,1,2]
PACKAGE=[1,1,2,1,2,3,3]
df=pd.DataFrame({'user':USER,'package':PACKAGE})
results=df.groupby(['user','package']).size()
results=results.sort_values(ascending=False)
results=results.unstack(level='package').fillna(0)
results=results.rename(columns={1:'First',2:'Second',3:'Third'})
print(results)
output:
package First Second Third
user
1 3.0 2.0 1.0
2 0.0 0.0 1.0
用户1的最高频率包为类型1,第二高频率包为类型2,第三高频率包为类型3。用户2的最高等级是类型3。您可以对结果进行查找以生成此输出。
尝试使用Groupby
:
df.groupby(['X']).get_group('A')