我有两个Pandas 数据帧,我想找到第二个数据帧中出现特定值的所有条目.

举个例子:

df1:
   NID
0    1
1    2
2    3
3    4
4    5

df2:
   EID  N1  N2  N3  N4
0    1   1   2  13  12
1    2   2   3  14  13
2    3   3   4  15  14
3    4   4   5  16  15
4    5   5   6  17  16
5    6   6   7  18  17
6    7   7   8  19  18
7    8   8   9  20  19
8    9   9  10  21  20
9   10  10  11  22  21

现在,我基本上想要的是具有值eid(来自df2)的列表列表,其中值nid(来自df1)出现在列n1、n2、n3、n4中的任一列中:

解决方案将是:

sol = [[1], [1, 2], [2, 3], [3, 4], [4, 5]]

所需的解决方案解释为:

该解决方案有5个条目(len(sol=5)),因为我在df1中有5个条目. SOL中的第一个条目是1,因为值NID=1仅出现在df2中EID=1的列N1、N2、N3、N4中. SOL中的第二个条目指的是值NID=2(对于DF1),并且具有长度2,因为NID=2可以在列N1(对于EID=2)和列N2(对于EID=1)中找到.因此,解决方案中的第二个条目是[1,2],依此类推.

到目前为止,我try 的是对df1中的每个元素进行循环,然后对df2中的每个元素进行循环,以查看nid是否在列n1、n2、n3、n4中.这个解决方案是有效的,但是对于巨大的数据帧(每个DF可以有多达数千个条目),这个解决方案变得非常耗时. 因此,我在寻找一种更有效的解决方案.

我已实现的代码如下:

输入数据:

import pandas as pd
df1 = pd.DataFrame({'NID':[1,2,3,4,5]})
df2 = pd.DataFrame({'EID':[1,2,3,4,5,6,7,8,9,10],
                  'N1':[1,2,3,4,5,6,7,8,9,10],
                  'N2':[2,3,4,5,6,7,8,9,10,11],
                  'N3':[13,14,15,16,17,18,19,20,21,22],
                  'N4':[12,13,14,15,16,17,18,19,20,21]})

使用循环获得的解决方案:

sol= []

for idx,node in df1.iterrows():
    x = []
    for idx2,elem in df2.iterrows():
        if node['NID'] == elem['N1']:
            x.append(elem['EID'])
        if node['NID'] == elem['N2']:
            x.append(elem['EID'])
        if node['NID'] == elem['N3']:
            x.append(elem['EID'])
        if node['NID'] == elem['N4']:
            x.append(elem['EID'])
    sol.append(x)

print(sol)

如果有人有一个解决方案,我不需要循环,我会非常高兴.也许使用NumPy函数或类似cKDTrees的东西,但不幸的是,我不知道如何以更快的方式解决这个问题.

提前谢谢您!

推荐答案

您可以使用melt进行reshape ,使用loc进行过滤,并将groupby.agg作为列表.然后reindex和转换tolist:

out = (df2
    .melt('EID')   # reshape to long form
    # filter the values that are in df1['NID']
    .loc[lambda d: d['value'].isin(df1['NID'])]
    # aggregate as list
    .groupby('value')['EID'].agg(list)
    # ensure all original NID are present in order
    # and convert to list
    .reindex(df1['NID']).tolist()
)

stack的替代方案:

df3 = df2.set_index('EID')

out = (df3
    .where(df3.isin(df1['NID'].tolist())).stack()
    .reset_index(name='group')
    .groupby('group')['EID'].agg(list)
    .reindex(df1['NID']).tolist()
)

输出:

[[1], [2, 1], [3, 2], [4, 3], [5, 4]]

Python-3.x相关问答推荐

为什么vs code返回错误—LocaleError:int对象没有属性where,但相同的代码运行在Google Colab上没有任何问题''''

Python将类实例变量转换为嵌套 struct

Django将任何查询显示为html表格

在BaseHTTPRequestHandler中填充和返回列表

如何在 python 中将带有时区信息的时间戳转换为 utc 时间

CSV-DAT 转换时将引号添加到数据中

无法提出给定 for 循环的原因 (Python 3.11)

在 python f-string 中使用 \u

attrs 将 list[str] 转换为 list[float]

过滤并获取数据框中条件之间的行

使用正则表达式提取字符串之间的文本

spaCy 中的匹配模式返回空结果

使用 pandas 进行多类分类的总体准确度

删除重复项,但将值相加为一

每个数据行中每个数据帧值的总和

Visual Studio Code 中的 Python 3.x 类型提示

Python:如何在三个列表中找到共同值

如何使用pandas python获取数据框中每列的最大长度

tkinter TclError:错误的文件类型使用 askopenfilename

谁能给我一个 Python 3 中标准输入和标准输出的快速教程?