根据列表过滤列表的熊猫列

时间:2018-11-01 20:54:12

标签: python pandas

具有较大的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

3 个答案:

答案 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