Я хочу создать столбец «Проведено?» в моем кадре данных pandas, который помечается всякий раз, когда символ в одной из ячеек «DrpType» содержится в другой ячейке «HeldDrpTypes» из той же строки.
Я пробовал использовать where и in, но это не сработало:
df['Held?'] = where(df['DrpType'] in df['HeldDrpTypes'] == True),'Yes','No')
Вот чего я хочу добиться:
> print(df)
DrpType HeldDrpTypes Held?
0 A B No
1 B BC Yes
2 C B No
3 B BC Yes
4 A BC No
5 C BC Yes
Любые идеи, как я могу это сделать?






Вы можете проверить
l=['Yes' if x in y else 'No' for x , y in zip(df.DrpType,df.HeldDrpTypes)]
l
Out[196]: ['No', 'Yes', 'No', 'Yes', 'No', 'Yes']
df['Held']=l
Или воспользуемся методом из numpy
np.core.chararray.find(df.HeldDrpTypes.values.astype(str),df.DrpType.values.astype(str))!=-1
Out[201]: array([False, True, False, True, False, True])
Если вам интересно, сделал некоторые тайминги
Для чистого пути панд вы можете использовать df.apply()
import pandas as pd
df = pd.DataFrame({
'DrpType': ['A', 'B', 'C', 'B', 'A', 'C',],
'HeldDrpTypes':['B', 'BC', 'B', 'BC', 'BC', 'BC']
})
df['Held?'] = df.apply(lambda row: row['DrpType'] in row['HeldDrpTypes'], axis=1)
print(df)
# DrpType HeldDrpTypes Held?
# 0 A B False
# 1 B BC True
# 2 C B False
# 3 B BC True
# 4 A BC False
# 5 C BC True
Если вы сторонник Yes/No, а не True/False, вы можете использовать следующее, но я бы посоветовал придерживаться двоичного кода True/False, чтобы упростить проверку на правдивость, а не анализировать строку.
df['Held?'] = df.apply(
lambda row: 'Yes' if row['DrpType'] in row['HeldDrpTypes'] else 'No', axis='columns')
print(df)
# DrpType HeldDrpTypes Held?
# 0 A B No
# 1 B BC Yes
# 2 C B No
# 3 B BC Yes
# 4 A BC No
# 5 C BC Yes
Мне было интересно узнать время обоих ответов, поэтому я проверил их, используя больший фрейм данных:
df = pd.concat([df]*100000, ignore_index=True)
print(df.shape)
(600000, 2)
Вен-Бенс ответьте list comprehension:
%%timeit
df['Held'] = ['Yes' if x in y else 'No' for x , y in zip(df.DrpType,df.HeldDrpTypes)]
Выдает следующее:
304 ms ± 17.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Брайан Коханс ответьте, используя .apply
%%timeit
df['Held?'] = df.apply(
lambda row: 'Yes' if row['DrpType'] in row['HeldDrpTypes'] else 'No', axis='columns')
Выдает следующее:
23.2 s ± 1.23 s per loop (mean ± std. dev. of 7 runs, 1 loop each)
Таким образом, разница в скорости на самом деле составляет +- 1000 в пользу list comprehension
Это смешно! Хотя я думаю, я не очень шокирован тем, что понимание, являющееся родной идиомой Python, работает над двумя сериями быстрее, чем что-то, построенное с помощью Python, тащащего все содержимое фрейма данных. Это немного шокирует для фрейма данных буквально с двумя столбцами, но мне не хотелось бы думать о разнице во времени с более сложным фреймом данных. Спасибо за тестирование разницы. Очевидно, что нужно учитывать реальный размер ваших данных и удобочитаемость, но я обязательно должен помнить об этом в будущем.
Я и сам просчитывал цифры. Понимание списка с выводом Yes/No: 62 мс, метод numpy с выводом True/False: 456 мс. df.apply() метод с любым выходом: 11,7 с.
Интересно о таймингах, я думаю, что понимание списка может быть более чем в 1000 раз быстрее, чем метод
apply