Печать всех вхождений сопоставленных данных из 2 кадров данных в пандах

1

У меня есть 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. Могут ли помочь кому-нибудь?

  • 1
    Но почему должен быть включен SAP_Sec ? В df2 нет столбца, значения которого являются подмножеством значений столбцов в df1['SAP_Sec'] .
  • 0
    @jpp извините за поздний ответ. Но если вы видите первую строку sap sec, это подмножество, так как оно содержит одно из имен. Не знаю, как я пропустил этот комментарий. Но оцените ваши решения. :)
Теги:
pandas
dataframe
set

2 ответа

1
Лучший ответ

Я думаю, что нужно 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']})
  • 0
    Большой..!! Я никогда не работал с перекрестками. Спасибо за быструю помощь @jezrael
  • 1
    @ anky_91 - Надеюсь, все будет хорошо, удачи!
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
  • 0
    Спасибо @ jpp, однако код работает долго при использовании больших файлов. Мой фактический файл имеет 112444 строки × 446 столбцов, а целевой файл, который нужно изменить, имеет 3 строки × 35 столбцов. Но большое спасибо за помощь, буду ссылаться на это для будущих ссылок. :)
  • 1
    @ anky_91, для производительности вы можете попробовать any [см. сравнительный анализ внизу моего ответа].

Ещё вопросы

Сообщество Overcoder
Наверх
Меню