我的熊猫数据框的格式为
userID author_cat vote
234 1246 5.0
121 2954 3.2
234 1246 2.1
121 2954 1.4
234 1578 3.3
234 1246 4.5
121 2954 1.1
121 9341 3.2
预期
userID author_cat vote first_author second_author third_author
234 1246 5.0 1246 1578 0
121 2954 3.2 2954 9341 0
234 1246 2.1 1246 1578 0
121 2954 1.4 2954 9341 0
234 1578 3.3 1246 1578 0
234 1246 4.5 1246 1578 0
121 2954 1.1 2954 9341 0
121 9341 3.2 2954 9341 0
我想为每个用户根据他们的评分来构造三列。出现次数最多的作者(同一作者撰写的更多书籍,并由一个用户复审)应出现在“ first_preferred_author”列中(类别,如1246)。第二和第三首选作者也是如此。如果作者不存在(第一,第二和第三,甚至所有三个作者都不存在,则三个新列应包含0)。
到目前为止,我已经根据用户的评论数量设法获得了作者的出现顺序,
df_new.groupby('userID')['author_cat'].value_counts()
但是我不知道从这里做什么。
编辑:
上面的命令返回一个pd.series.series
(?),看起来像这样(在实际数据集上):
userID author_cat
243 42994.0 6
48986.0 5
72473.0 3
2505.0 2
4371.0 2
5270.0 2
18764.0 2
41267.0 2
75183.0 2
82066.0 2
486.0 1
571.0 1
3507.0 1
6343.0 1
6524.0 1
7530.0 1
10539.0 1
10679.0 1
21123.0 1
30948.0 1
41305.0 1
41479.0 1
43715.0 1
49236.0 1
52183.0 1
53204.0 1
56812.0 1
56916.0 1
57911.0 1
62266.0 1
..
278633 54862.0 1
57422.0 1
66639.0 1
72642.0 1
72712.0 1
73809.0 1
82105.0 1
87066.0 1
91189.0 1
93458.0 1
94608.0 1
96674.0 1
99025.0 1
278843 80852.0 3
3377.0 2
4371.0 2
2437.0 1
2528.0 1
5216.0 1
18370.0 1
30948.0 1
35706.0 1
37463.0 1
40577.0 1
62175.0 1
62645.0 1
81508.0 1
92206.0 1
92242.0 1
93801.0 1
Name: author_cat, Length: 96302, dtype: int64
答案 0 :(得分:3)
尝试一下:
(df.groupby(['userID']).author_cat
.apply(lambda x: pd.Series(x.value_counts()
.nlargest(3).index))
.unstack(level=1).fillna(0).astype(int))
示例(为多一位第三作者再添加一行121,2953,1.1
)
userID,author_cat,vote
234,1246,5.0
121,2954,3.2
234,1246,2.1
121,2954,1.4
234,1578,3.3
234,1246,4.5
121,2954,1.1
121,9341,3.2
121,2953,1.1
输出:
+--------+------+------+------+
| | 0 | 1 | 2 |
+--------+------+------+------+
| UserID | | | |
+--------+------+------+------+
| 121 | 2954 | 9341 | 2953 |
| 234 | 1246 | 1578 | 0 |
+--------+------+------+------+
答案 1 :(得分:0)
我不确定要为每列分配值。但是,您可以将nlargest
与groupby
结合使用,以获得每个用户的前三名作者:
df.groupby('userID').author_cat.value_counts().groupby('userID').nlargest(3)
userID author_cat
121 2954 3
9341 1
234 1246 3
1578 1
Name: author_cat, dtype: int64
假设您的示例df
与原始值计数相同,但是如果在完整数据集上运行它,则只会取回每个用户ID的前3个值计数。
答案 2 :(得分:0)
应该遵循以下步骤:
preferences = (
df
.groupby(['userID', 'author_cat'])
.size()
.rename('count')
.pipe(lambda x: pd.DataFrame(x))
.sort_values('count', ascending=False)
.groupby('userID')
.apply(lambda x: x.assign(rank=np.arange(len(x.index)) + 1)) # Adds incrementing rank even if counts are equal
.reset_index()
.set_index(['userID', 'rank'])
['author_cat']
.unstack(1) # This "pivots" the dataframe
.filter(lambda x: x <= 3, axis=1)
.rename(columns={1: 'first_author', 2: 'second_author', 3: 'third_author'})
.fillna(0)
.astype('int')
)
df = df.join(preferences, on='userID')
相对于groupby().size()
,我更喜欢value_counts()
,它给出相似的结果,但保留索引级别的名称。
此外,请注意,如果同一author_cat
的外观数量相同,则此实现不注意userID
的顺序。
答案 3 :(得分:0)
不使用apply
的解决方案。使用groupby.unique
按出现顺序获得一系列唯一author_cat
的列表。将其取消嵌套到数据框。将3列的值分别为0
至df
。 set_index
上的df
至userID
。最后,从update
的数据帧中提取groupby.unique
df:
d1 = df.groupby('userID')['author_cat'].unique()
d2 = pd.DataFrame(d1.tolist(), index=d1.index)
d2
Out[455]:
0 1
userID
121 2954 9341
234 1246 1578
最后一步:
df[0], df[1], df[2] = 0, 0, 0
df.set_index('userID', inplace=True)
df.update(d2)
Out[456]:
author_cat vote 0 1 2
userID
234 1246 5.0 1246.0 1578.0 0
121 2954 3.2 2954.0 9341.0 0
234 1246 2.1 1246.0 1578.0 0
121 2954 1.4 2954.0 9341.0 0
234 1578 3.3 1246.0 1578.0 0
234 1246 4.5 1246.0 1578.0 0
121 2954 1.1 2954.0 9341.0 0
121 9341 3.2 2954.0 9341.0 0
您的样本没有第三列值,因此列2
仍然位于0
之后的update
。
如果您的数据具有第三列值,则输出将如下所示(注意:在这种情况下,我向您的示例中添加了一行以演示第三列):
Out[462]:
author_cat vote 0 1 2
userID
234 1246 5.0 1246 1578 0.0
121 2954 3.2 2954 9341 9954.0
234 1246 2.1 1246 1578 0.0
121 2954 1.4 2954 9341 9954.0
234 1578 3.3 1246 1578 0.0
234 1246 4.5 1246 1578 0.0
121 2954 1.1 2954 9341 9954.0
121 9341 3.2 2954 9341 9954.0
121 9954 9954.0 2954 9341 9954.0