Проверка того, находятся ли значения в pandas df внутри списков в столбцах второго df

У меня есть 2 кадра данных df1: имеет 4 столбца, в каждом столбце есть список внутри со значениями df2: имеет один столбец (col) столбец имеет 1 значение

Я хочу проверить, находятся ли какие-либо значения в df2 (col) внутри любого из списков в строках df1 (col1) или df1 (col2), а затем сохранить эту строку (df1 с 4 столбцами)

Вот несколько случайных данных для примера:

df1 = pd.DataFrame({'col1': [[32, 24, 5, 6], [4, 8, 14], 
                            [12, 32, 234, 15, 6], [45]], 
                    'col2': [[13, 333 ,5], [32, 28, 5, 9], 
                            [4], [12, 45, 21]],
                    'col3': [['AS', 'EWE', 'SADF', 'EW'], 
                            ['EW', 'HHT', 'IYT'], ['C', 'KJG', 'TF', 'VC', 'D'], ['BX']], 
                    'col4': [['HG', 'FDGD' ,'F'], ['FDG', 'Y', 'FS', 'RT'], 
                            ['T'], ['XC', 'WE', 'TR']]
                    })

df2 = pd.DataFrame({'col': [1, 333, 8, 11, 45]})

дф1:

                   col1            col2                 col3              col4
0        [32, 24, 5, 6]    [13, 333, 5]  [AS, EWE, SADF, EW]     [HG, FDGD, F]
1            [4, 8, 14]  [32, 28, 5, 9]       [EW, HHT, IYT]  [FDG, Y, FS, RT]
2  [12, 32, 234, 15, 6]             [4]  [C, KJG, TF, VC, D]               [T]
3                  [45]    [12, 45, 21]                 [BX]      [XC, WE, TR]

дф2:

   col
0    1
1  333
2    8
3   11
4   45

Этот код отлично работает, но я использую большие данные, поэтому для завершения требуется много времени. Поэтому мне интересно, есть ли способ оптимизировать его.

for index, row in df1.iterrows():
    if (any(itm in row['col1'] for itm in df2['col'])):
        df3 = df3.append(row)
    elif (any(itm in row['col2'] for itm in df2['col'])):
        df3 = df3.append(row)

И вот как будет выглядеть вывод:

             col1            col2                 col3              col4
0  [32, 24, 5, 6]    [13, 333, 5]  [AS, EWE, SADF, EW]     [HG, FDGD, F]
1      [4, 8, 14]  [32, 28, 5, 9]       [EW, HHT, IYT]  [FDG, Y, FS, RT]
3            [45]    [12, 45, 21]                 [BX]      [XC, WE, TR]

Вывод может быть либо новым df, либо столбцом в df1 с «1» или «0», если значение находится или нет в любом из двух столбцов.

ОБНОВЛЯТЬ:

Следуя подходу cs95, я смог улучшить производительность кода.

Мой предыдущий код занял 55 с, с его подходом это всего 8 мс, поэтому ускорение составляет около x690.

Здравствуйте и спасибо, что приняли. Каков фактор ускорения исправленного решения?

cs95 18.12.2020 23:39

Привет, спасибо за помощь! Я буду больше думать о написании более эффективного кода. Фактор ускорения был около x690

Luis Orellana 18.12.2020 23:42
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
2
107
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Конечно, мы можем использовать setlookups, чтобы ускорить это:

lookup = {*df2['col']}
df1[~df1[['col1', 'col2']].applymap(lookup.isdisjoint).all(axis=1)]

             col1            col2                 col3              col4
0  [32, 24, 5, 6]    [13, 333, 5]  [AS, EWE, SADF, EW]     [HG, FDGD, F]
1      [4, 8, 14]  [32, 28, 5, 9]       [EW, HHT, IYT]  [FDG, Y, FS, RT]
3            [45]    [12, 45, 21]                 [BX]      [XC, WE, TR]

Работать со столбцом списков сложно. Мы можем упростить задачу, признав, что можем использовать applymap, поскольку каждая ячейка в df1['col1'] и df1['col2'] должна пройти одинаковую проверку (поиск в df2['col']). Затем используйте небольшую логическую логику, чтобы определить, какие строки нужно удалить, и вы получите окончательный результат.

Ваш код содержит двойной удар с использованием iterrows и append. Никогда не перебирайте DataFrame, потому что это медленно и занимает много памяти, и никогда не увеличивайте DataFrame по тем же причинам.


lookup
# {1, 8, 11, 45, 333}

# get cells that have no elements in common
df1[['col1', 'col2']].applymap(lookup.isdisjoint)

    col1   col2
0   True  False
1  False   True
2   True   True
3  False  False

# get rows who have no columns in common
df1[['col1', 'col2']].applymap(lookup.isdisjoint).all(axis=1)
 
0    False
1    False
2     True
3    False
dtype: bool

# invert the condition to get rows to keep
~df1[['col1', 'col2']].applymap(lookup.isdisjoint).all(axis=1)

0     True
1     True
2    False
3     True
dtype: bool

Другие вопросы по теме