[英]Filter pandas column of lists based on a list
具有一个较大的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
列已经由其他用户提到的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
这不是非常适合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
当然,您不应该将清单放在熊猫系列中。 这是一个嵌套的指针层,应尽可能避免使用。
完成编辑后,我必须同意@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
这是一种方法。
# 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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.