Pandas,值的组合并检查列表中是否有任何组合

问题描述 投票:0回答:1

我有一个

df1
,每个项目都有一些
item_id
和一些值(称为“节点”):

df1 = pd.DataFrame({'item_id':['1','1','1','2','2','2','3','3'],'nodes':['a','b','c','d','a','e','f','g']})

和一个

df2
,它是一个“向量”列表,其中每一行都是一个节点元组(可以在
df1
中,但其中一些不是):

df2=pd.DataFrame({'vectors':[('a','b'),('b','c'),('d','f'),('e','b')]})

我需要计算

item_id
中不同
df1
的数量,它们在
df2
中至少有一个向量,因为可以从该项目的所有可能的节点组合构造一个向量。

例如

item_id = 1
有节点
[a,b,c]
,所以可以组成这些向量:
[(a,b),(a,c),(b,a),(b,c),(c,a),(c,b)]
。由于向量
(a,b)
(b,c)
存在于
df2
中,那么我应该算
item_id = 1
。但是,我不应该计算
item_id = 2
,因为从其节点组合可以形成的所有向量中,它们都不在
df2
中。

我不知道我怎样才能做到这一点。我可以获得节点所有可能组合的列表,以形成

item_id
中第一个
df1
的不同向量,使用:

from itertools import product
nodes_fa=df1[df1.item_id=="1"].nodes.to_list()
vectors_fa = pd.DataFrame(product(nodes_fa,nodes_fa),columns=['u','v'],dtype='str')
vectors_fa['vector'] = vectors_fa[["u", "v"]].agg(tuple, axis=1)
vectors_fa = vectors_fa[['vector']]
display(vectors_fa)

但我不知道如何将其扩展到所有

item_id
,也不知道如何检查此列表中的任何值是否在循环中的
df2
中。

任何帮助将不胜感激。

python pandas dataframe combinations
1个回答
0
投票

您可以使用

itertools.combinations
groupby.apply
,在
set
/
frozenset
的帮助下:

考虑无向边(

('a', 'b')
==
('b', 'a')
):

from itertools import combinations

S = set(frozenset(x) for x in df2['vectors'])

out = (
 df1.groupby('item_id')['nodes']
    .apply(lambda g: any(frozenset(t) in S for t in combinations(g, r=2)))
    .sum()
)

对于有向边(

('a', 'b')
!=
('b', 'a')
):

from itertools import combinations

S = set(df2['vectors'])

out = (
 df1.groupby('item_id')['nodes']
    .apply(lambda g: any(t in S for t in combinations(g, r=2)))
    .sum()
)

输出:

1

使用 pandas 函数的替代方案(可能效率较低):

s = (df1.groupby('item_id')['nodes']
        .agg(lambda g: list(combinations(g, r=2)))
        .explode()
     )

out = s.isin(df2['vectors']).groupby(level=0).any().sum()
© www.soinside.com 2019 - 2024. All rights reserved.