Учитывая следующие два dataframes:

df1 = pd.DataFrame(data={'unicorn': ['blue', 'red', 'piNk'], 'size': [3, 4, 6]})
df2 = pd.DataFrame(data={'unicorn': ['red'], 'size': [2]})

Df1:

  unicorn  size
0    blue     3
1     red     4
2    piNk     6

Df2 (всегда имеет одну строку):

  unicorn  size
0     red     2

Как я могу сравнить строки обоих столбцов dataframes, используя пользовательские функции сравнения, подобные этому (упрощенному):

def unicorn_comparison(str1, str2) -> float:
  return 100.0 if str1 == str2 else 0.0

А также

def size_comparison(nr1, nr2) -> float:
  return 100.0 if nr1 < nr2 else 0.0

Ожидаемый результат:

   unicorn  size
0      0.0   0.0
1    100.0   0.0
2      0.0   0.0
3
DeepLearningEel 26 Янв 2022 в 16:11
Что делать, если в df2 больше строк? Вы можете обновить свой пример? Можно подробнее про "реальную" функцию, можно ли ее векторизовать?
 – 
mozway
26 Янв 2022 в 16:21
Обновленный ответ. Что касается «реальных» функций: каждая функция всегда сравнивает ровно две переменные и возвращает число с плавающей запятой.
 – 
DeepLearningEel
26 Янв 2022 в 16:26
ОК, спасибо за пояснение, я предоставил ответ, однако знайте, что двойной цикл с пользовательской функцией может быть очень медленно. Чтобы оптимизировать это, попробуйте привести более содержательный пример того, что на самом деле делает пользовательская функция.
 – 
mozway
26 Янв 2022 в 16:36
Обновлен ответ, чтобы показать, что я работаю с несколькими функциями.
 – 
DeepLearningEel
26 Янв 2022 в 16:40

3 ответа

Лучший ответ

Поскольку у вас всегда есть одна строка в df2, используйте не DataFrame (2D), а Series (1D).

ser = df2.loc[0]

Затем, если вам просто нужно сравнение, используйте векторный код (а не пользовательскую функцию):

out = df1.eq(ser)*100

Если вам действительно нужно использовать невекторную функцию и сравнивать все комбинации, используйте:

def unicorn_comparison(str1, str2) -> float:
    return 100.0 if str1 == str2 else 0.0

def size_comparison(nr1, nr2) -> float:
    return 100.0 if nr1 < nr2 else 0.0

funcs = {'unicorn': unicorn_comparison,
         'size': size_comparison
        }

out = df1.apply(lambda c: c.apply(lambda s: funcs[c.name](s, ser[c.name])))

Выход:

   unicorn  size
0        0     0
1      100     0
2        0     0

1
mozway 26 Янв 2022 в 16:42
Спасибо. Просто интересно, насколько эффективно это будет с несколькими пользовательскими функциями?
 – 
DeepLearningEel
26 Янв 2022 в 16:42
Я обновил код для нескольких функций. Я не знаю, сколько у вас столбцов/строк и что на самом деле делают функции, поэтому я не могу ответить относительно скорости. Вы должны дать нам обратную связь ;)
 – 
mozway
26 Янв 2022 в 16:44
У меня не более 8 строк в df1. Любите решение. Спасибо!
 – 
DeepLearningEel
26 Янв 2022 в 16:45
И максимум 6 столбцов.
 – 
DeepLearningEel
26 Янв 2022 в 16:52
Тогда это должно быть довольно быстро, если только ваши функции сравнения сами по себе не очень медленные;)
 – 
mozway
26 Янв 2022 в 16:53

Свой путь. первый; добавьте нужный столбец df2.

df1['unicorn2'] = df2['unicorn']

После; Вы можете использовать «цикл приложения». Вы можете запустить логику, которую хотите, в «цикле приложения».

def function(x):
    # your logic
  return x
df1_result = df1.apply(function)
0
Zendem 26 Янв 2022 в 16:31
А остальные столбцы?
 – 
DeepLearningEel
26 Янв 2022 в 16:52
for col in df1:
    df1[col] = (df1[col] == df2[col].loc[0]).replace({True: 100, False: 0})

Это перезапишет ваш df1, или вы можете сначала сделать его копию.

0
Raymond Kwok 26 Янв 2022 в 16:35