我有一个仅包含两列 user_id 和 channel 的数据集。 channel 列可以采用预定义列表 [a,b,c,d] 中的值。有多行具有相同的 user_id。每行可以包含上述任何 channel 。
如果我考虑每个用户访问的独特 channel ,哪一组出现频率最高?
示例数据框:
>>> df = pd.DataFrame([[1, 'a'], [1, 'b'], [1, 'b'], [1,'b'], [2,'c'], [2,'a'], [2,'a'], [2,'b'], [3,'a'], [3,'b']], columns=['user_id', 'Channel'])
>>> df
user_id Channel
0 1 a
1 1 b
2 1 b
3 1 b
4 2 c
5 2 a
6 2 a
7 2 b
8 3 a
9 3 b
预期的解决方案:
上面的例子是这样的:
- 对于
user_id == 1,一组唯一的 channel 是{a, b},并且对于该组合只计算一次。 - 对于
user_id == 2唯一 channel 集是{a, b, c}并且该组合计数一次。请注意,这不计入这些独特 channel 的任何子集。 - 对于
user_id == 3,一组唯一的 channel 是{a, b},并且该组合只计算一次。
如果我们计算每个 user_id 的一个唯一 channel 组合,我们应该得到
>>> df_result = pd.DataFrame([['a,b', 2], ['a,b,c', 1]], columns=['Channels_together', 'n'])
>>> df_result
Channels_together n
0 a,b 2
1 a,b,c 1
我想出了一个解决方案,即旋转表,以便我得到 user_id 和列 a、b、c, d 然后为每个 Channel 列分配一个整数(如果不是 NA),然后跨列求和并将结果转换回每个组合。
我确信有更好的方法可以做到这一点,但我似乎无法找到方法。
请您参考如下方法:
您可以使用 groupby.apply(set) 然后使用 .value_counts 计算值:
df.groupby('user_id')['Channel'].apply(set).value_counts()\
.reset_index(name='n')\
.rename(columns={'index':'Channels_together'})
输出
Channels_together n
0 {a, b} 2
1 {a, c, b} 1
如果您希望您的值采用 str 格式,我们可以编写一个 lambda 函数来对我们的集合进行排序并将其转换为字符串:
df.groupby('user_id')['Channel'].apply(lambda x: ', '.join(sorted(set(x)))).value_counts()\
.reset_index(name='n')\
.rename(columns={'index':'Channels_together'})
输出
Channels_together n
0 a, b 2
1 a, b, c 1
