将一个dataframes列折叠成它不同的值,并基于另一个频率创建一个新列



我想取一个数据框架,如:

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')

最新更新