具有较大的DataFrame
,如下所示:
userid user_mentions
1 [2, 3, 4]
1 [3]
2 NaN
2 [1,3]
3 [1,4,5]
3 [4]
user_mentions
列是每个用户提到的userid
的列表。例如,第一行表示:
用户1提到了用户2、3和4。
我需要在userid
列中的用户之间创建提及网络。也就是说,我想要userid
列中的其他用户提到userid
列中的每个用户的次数。所以基本上,首先我需要这样的东西:
filtered = df[df['user_mentions'].isin(df['userid'].unique())]
但这不适用于列表的列。
如果我解决了上述问题,则可以groupby['userid','user_mentions']
。
编辑
最终输出应为:
Source Target Number
1 2 1
1 3 2
2 1 1
2 3 1
3 1 1
3 5 1
答案 0 :(得分:4)
这不是非常适合Pandas / NumPy的任务。因此,我建议您使用collections.defaultdict
创建一个计数字典,然后从该字典构造一个数据框:
from collections import defaultdict
dd = defaultdict(lambda: defaultdict(int))
for row in df.itertuples(index=False):
vals = row.user_mentions
if vals == vals:
for val in vals:
dd[row.userid][val] += 1
df = pd.DataFrame([(k, w, dd[k][w]) for k, v in dd.items() for w in v],
columns=['source', 'target', 'number'])
print(df)
source target number
0 1 2 1
1 1 3 2
2 1 4 1
3 2 1 1
4 2 3 1
5 3 1 1
6 3 4 2
7 3 5 1
当然,您不应该将列表放在Pandas系列中。这是一个嵌套的指针层,应尽可能避免使用它。
答案 1 :(得分:1)
在您进行编辑之后,我必须同意@jpp。
对于您的(未编辑的)原始问题,就收集每个用户的提及数而言,您可以执行以下操作:
df['counts'] = df['userid'].apply(lambda x: df['user_mentions'].dropna().sum().count(x))
df[['userid','counts']].groupby('userid').first()
收益:
counts
userid
1 2
2 1
3 3
答案 2 :(得分:1)
这是一种方法。
# Remove the `NaN` rows
df = df.dropna()
# Construct a new DataFrame
df2 = pd.DataFrame(df.user_mentions.tolist(),
index=df.userid.rename('source')
).stack().astype(int).to_frame('target')
# Groupby + size
df2.groupby(['source', 'target']).size().rename('counts').reset_index()
source target counts
0 1 2 1
1 1 3 2
2 1 4 1
3 2 1 1
4 2 3 1
5 3 1 1
6 3 4 2
7 3 5 1