#python #pandas #dataframe #lambda #apply
#python #pandas #dataframe #лямбда #применить
Вопрос:
Привет, сообщество,
Я прочитал так много ответов и блогов, но я не могу понять, какую простую вещь я упускаю!. Я использую функцию ‘conditions’, чтобы определить все условия и применить ее к одному столбцу dataframe. И если условие удовлетворяет, оно должно создать / обновить 2 новых столбца фрейма данных ‘cat’ и ‘subcat’.
Было бы большим подспорьем, если бы вы, ребята, могли мне здесь помочь!
dict = {'remark':['NA','NA','Category1','Category2','Category3'],
'desc':['Present','Present','NA','Present','NA']
}
df = pd.DataFrame(dict)
Фрейм данных выглядит примерно так:
remark desc
0 NA Present
1 NA Present
2 Category1 NA
3 Category2 Present
4 Category3 NA
Я написал функцию для определения условий, как показано ниже:
def conditions(s):
if (s == 'Category1'):
x = 'insufficient'
y = 'resolution'
elif (s=='Category2):
x= 'insufficient'
y= 'information'
elif (s=='Category3):
x= 'Duplicate'
y= 'ID repeated'
else:
x= 'NA'
y= 'NA'
return (x,y)
У меня есть несколько идей по выполнению вышеупомянутой функции в столбце dataframe, но безуспешно.
df[['cat','subcat']] = df['remark'].apply(lambda x: pd.Series([conditions(df)[0],conditions(df)[1]]))
Мой ожидаемый фрейм данных должен выглядеть примерно так:
remark desc cat subcat
0 NA Present NA NA
1 NA Present NA NA
2 Category1 NA insufficient resolution
3 Category2 Present insufficient information
4 Category3 NA Duplicate ID repeated
Большое спасибо.
Ответ №1:
Один из способов обойти это — использовать понимание списка :
df[['cat', 'subcat']] = [("insufficient", "resolution") if word == "Category1" else
("insufficient", "information") if word == "Category2" else
("Duplicate", "ID repeated") if word == "Category3" else
("NA", "NA")
for word in df.remark]
remark desc cat subcat
0 NA Present NA NA
1 NA Present NA NA
2 Category1 NA insufficient resolution
3 Category2 Present insufficient information
4 Category3 NA Duplicate ID repeated
Ответ @dm2 показывает, как это сделать с помощью вашей функции. Первый apply(conditions)
создает серию, содержащую кортежи, второй apply
создает отдельные столбцы, формируя фрейм данных, который затем можно присвоить cat
и subcat
.
Причина, по которой я предлагаю использовать понимание списка, заключается в том, что вы имеете дело со строками, а в Pandas работа со строками через vanilla python чаще всего выполняется быстрее. Кроме того, при понимании списка обработка выполняется один раз, вам не нужно применять функцию conditions и затем вызывать pd.Series
. Это дает вам более высокую скорость. Тестирование подтвердит или опровергнет это.
Комментарии:
1. Мне нравится ваша идея понимания списка. Я пробовал то же самое ранее, но поскольку столбец (‘cat’ amp;’subcat’) отсутствует в df. это выдает ‘KeyError’. Есть идея? Ошибка ключа: «Ни один из [Index([‘cat’, ‘subcat’], dtype=’object’)] не находится в [index]»
2. Да, используя timeit, это намного, намного быстрее: среднее значение 7 запусков по 1000 попыток для моего кода составляет 0,3 с, ваш код выполняется так же за 0,009 с.
3. я не уверен, почему у вас эта ошибка @nealkaps — приведенный выше код должен создать два новых столбца. Если вы используете ноутбук, вы могли бы перезапустить ядро и снова запустить ячейку.
Ответ №2:
Вы могли бы сделать:
df[['cat','subcat']] = df['remark'].apply(conditions).apply(pd.Series)
Вывод:
remark desc cat subcat
0 NA Present NA NA
1 NA Present NA NA
2 Category1 NA insufficient resolution
3 Category2 Present insufficient information
4 Category3 NA Duplicate ID repeated
Редактировать: Это может быть более простым способом применить вашу функцию, которая у вас уже есть, но в случае, если у вас огромный фрейм данных, для более быстрого кода ознакомьтесь с ответом @sammywemmy, используя понимание списка.
Ответ №3:
Вы передаете все, dataframe
где вам просто нужно передать лямбда-переменную ( x
).
df[['cat','subcat']] = df['remark'].apply(lambda x: pd.Series([*conditions(x)]))
*
в iterables можно unpack
использовать их, поэтому вам не нужно вызывать одну и ту же функцию дважды для извлечения выходных данных. Возможно, компилятор решает это, но я так не думаю…
Ответ №4:
Вы можете использовать series.replace
со словарем сопоставления
df['cat'] = df.remark.replace({'Category1': 'insufficient',
'Category2': 'insufficient', 'Category3': 'Duplicate'})
df['subcat'] = df.remark.replace({'Category1': 'resolution',
'Category2': 'information', 'Category3': 'ID repeated'})
print(df)
remark desc cat subcat
0 NA Present NA NA
1 NA Present NA NA
2 Category1 NA insufficient resolution
3 Category2 Present insufficient information
4 Category3 NA Duplicate ID repeated