Как передать несколько аргументов из фрейма данных pandas в функцию и вернуть результат в фрейм данных в определенных местах в фрейме данных

1

Допустим, у меня есть следующий кадр данных pandas со следующей структурой столбца, а dataframe называется df

index column1 column2 column3
0     2       5       apple
1     4       3       apple
2     6       1       orange 
3     8       6       apple 
4    10       5       orange

Я хотел бы искать в dataframe так, чтобы он распознавал каждую строку, где df['column3'] == orange и извлекал значение df['column1'] и df['column2'] в этой строке и вставлял их в ниже, а затем измените существующее значение df[column2'] на выход функции.

def func(x, y):
    return x * 2.0

До сих пор я реализовал следующее, которое работает, но я подозреваю, что это не самый питонический способ сделать это и, вероятно, не имеет самой эффективной скорости выполнения. Любой совет будет принят во внимание.

for i in range(len(df.index)):
    if df.loc[i, 'column3'] == 'orange':
        df.loc[i, 'column2'] = func(df.column1, df.column2)
Теги:
pandas
dataframe
python-3.x

3 ответа

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

Гнездо вашего условия в применении:

In [26]: df
Out[26]:
       column1  column2 column3
index
0            2        5   apple
1            4        3   apple
2            6        1  orange
3            8        6   apple
4           10        5  orange

In [27]: df['column2'] = df.apply(lambda x: func(x['column1'], x['column2']) \
if x['column3'] == 'orange' else x['column2'], axis=1)

In [28]: df
Out[28]:
       column1  column2 column3
index
0            2      5.0   apple
1            4      3.0   apple
2            6     12.0  orange
3            8      6.0   apple
4           10     20.0  orange
  • 1
    Спасибо, это очень хорошо сработало для моей проблемы и избавило меня от необходимости переписывать функцию.
  • 0
    Я должен понизить это, поскольку троичные выражения в pd.DataFrame.apply на самом деле не являются pd.DataFrame.apply .
2

Нет необходимости использовать apply.

Вы можете просто использовать loc и маску.

mask = df['column3'] == "orange"
df.loc[mask, "column2"] = func(df.loc[mask].column1, df.loc[mask].column2)

Это проще и быстрее, чем применимо.

  • 0
    У вас есть ссылка на «быстрее»? Кажется также, что ваш функционал должен быть изменен для работы с сериями. Делает это менее простым.
  • 0
    @jpp Откуда вы взяли это требование? Функция отлично работает с сериями как есть . Здесь нет необходимости в универсальной функции. Если ОП нужна более сложная логика, я бы с вами согласился. Но это не так.
Показать ещё 2 комментария
0

Используя pd.DataFrame.apply, вы можете определить функцию, которая применяется к каждой строке последовательно. Обратите внимание, что строка передается вашей функции как объект серии и может быть распакована в поля компонентов через row['col_name'] синтаксиса row['col_name'].

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

def func(row):
    x = row['column1']
    y = row['column2']
    if row['column3'] == 'orange':
        return x * 2.0
    else:
        return y

df['column2'] = df.apply(func, axis=1)

print(df)

   index  column1  column2 column3
0      0        2      5.0   apple
1      1        4      3.0   apple
2      2        6     12.0  orange
3      3        8      6.0   apple
4      4       10     20.0  orange
  • 0
    К сожалению, это решение требует, чтобы я изменил природу функции, что я не могу сделать, потому что она используется в другом месте в программе. Это начинает казаться, что цикл for - единственный способ, которым я могу это сделать.

Ещё вопросы

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