从大熊猫的2个数据框中打印所有出现的映射数据

时间:2018-07-30 08:59:13

标签: python pandas dataframe set

我有一个数据框:df1

  SAP_Name  SAP_Class  SAP_Sec
  Avi       5          Avi
  Rison     6          A 
  Slesh     7          B 
  San       8          C 
  Sud       7          B 

df2:

Name_Fi Class std
Avi     5     fgh
Rison   6     Rij
Slesh   7     jkh

我正在尝试根据2个数据帧的列中包含的值来获取标头的映射。

使用以下代码时:

dfs1 = {col1: df1[col1].drop_duplicates() for col1 in df1.columns}
set2 = {col2: set(df2[col2]) for col2 in df2.columns}
d = {}
for col2, v2 in set2.items():
    for col1, v1 in dfs1.items():
        cond = set(v2).issubset(v1)
        if cond:
           d[col2] = col1
print(d)

我得到一个结果:

{'Name_Fi': 'SAP_Name', 'Class': 'SAP_Class'}

所需的输出:

{'Name_Fi': ['SAP_Name','SAP_Sec'], 'Class': 'SAP_Class'}

基本上尝试在df1中有匹配值的任何地方打印每个匹配的列标题。胸膜肺炎可以帮助吗?

2 个答案:

答案 0 :(得分:1)

我认为在intersection之间需要set,因此为了提高性能,dict comprehension将字典的两个值都转换为set s:

from collections import defaultdict

dfs1 = {col1: set(df1[col1].drop_duplicates()) for col1 in df1.columns}
set2 = {col2: set(df2[col2]) for col2 in df2.columns}

d = defaultdict(list)
for col2, v2 in set2.items():
    for col1, v1 in dfs1.items():
        cond = v2.intersection(v1)
        if cond:
           d[col2].append(col1)
print(d)
defaultdict(<class 'list'>, {'Name_Fi': ['SAP_Name', 'SAP_Sec'], 'Class': ['SAP_Class']})

答案 1 :(得分:1)

您不是在这里寻找issubset,因为这仅在一列中的值是另一列中的值的子集(例如, 所有 df2['Name_Fi']的值包含在df1['SAP_Sec']中。相反,您可以使用set.intersection或语法糖&来检查是否存在是任何重叠。

您可以将此想法与collections.defaultdict结合使用,以提取所需的结果:

from collections import defaultdict

d = defaultdict(list)
for col2, v2 in set2.items():
    for col1, v1 in dfs1.items():
        cond = set(v2) & set(v1)
        if cond:
            d[col2].append(col1)

print(d)

defaultdict(<class 'list'>, {'Name_Fi': ['SAP_Name', 'SAP_Sec'],
                             'Class': ['SAP_Class']})

更有效地,您可以在理解中计算set个对象,以避免在嵌套循环中进行显式转换:

from collections import defaultdict

dfs1 = {col1: set(df1[col1]) for col1 in df1}
set2 = {col2: set(df2[col2]) for col2 in df2}

d = defaultdict(list)

for col2, v2 in set2.items():
    for col1, v1 in dfs1.items():
        if v2 & v1:
            d[col2].append(col1)

print(d)

对于更大的数组,您可能会发现将pd.Series.unique + any与生成器表达式结合使用会更有效:

import pandas as pd
import numpy as np

np.random.seed(0)
A = pd.Series(np.random.randint(0, 1000, 10000)).unique()
B = pd.Series(np.random.randint(0, 100000, 10000)).unique()

%timeit np.in1d(B, A).any()     # 1.1 ms per loop
%timeit set(A) & set(B)         # 1.46 ms per loop
%timeit any(i in B for i in A)  # 102 µs per loop