У меня есть dataframe: 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. Могут ли помочь кому-нибудь?
Я думаю, что нужно intersection
между set
s, поэтому для выполнения было в 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']})
Здесь вы не ищете 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
any
[см. сравнительный анализ внизу моего ответа].
SAP_Sec
? Вdf2
нет столбца, значения которого являются подмножеством значений столбцов вdf1['SAP_Sec']
.