У меня есть данные, представленные с помощью pandas DataFrame, которые, например, выглядят следующим образом:
| id | entity | name | value | location
где id
— это значение integer
, entity
— это integer
, name
— это string
, value
— это integer
, а location
— это string
(например, США, Калифорния, Великобритания и т. д.).
Теперь я хочу добавить в этот фрейм данных новый столбец, столбец «flag
», где значения присваиваются следующим образом:
for d in df.iterrows():
if d.entity == 10 and d.value != 1000 and d.location == CA:
d.flag = "A"
elif d.entity != 10 and d.entity != 0 and d.value == 1000 and d.location == US:
d.flag = "C"
elif d.entity == 0 and d.value == 1000 and d.location == US"
d.flag = "B"
else:
print("Different case")
Есть ли способ ускорить это и использовать некоторые встроенные функции вместо цикла for?
Используйте np.select
, в котором вы передаете список условий, на основе этих условий вы даете ему выбор, и вы можете указать значение по умолчанию, когда ни одно из условий не выполняется.
conditions = [
(d.entity == 10) & (d.value != 1000) & (d.location == 'CA'),
(d.entity != 10) & (d.entity != 0) & (d.value == 1000) & (d.location == 'US'),
(d.entity == 0) & (d.value == 1000) & (d.location == 'US')
]
choices = ["A", "C", "B"]
df['flag'] = np.select(conditions, choices, default = "Different case")
Нет, это векторизованное решение. Циклы в общем питоне и пандах медленные. Поэтому используйте последнюю строку, чтобы создать новый столбец с именем flag
. @Зива
Добавьте ()
с побитовым and
-> &
для работы с numpy.select
:
m = [
(d.entity == 10) & (d.value != 1000) & (d.location == 'CA'),
(d.entity != 10) & (d.entity != 0) & (d.value == 1000) & (d.location == 'US'),
(d.entity == 0) & (d.value == 1000) & (d.location == 'US')
]
df['flag'] = np.select(m, ["A", "C", "B"], default = "Different case")
Вы написали «найти все столбцы, которые удовлетворяют набору условий», но ваш код показывает, что вы на самом деле пытаетесь добавить новый столбец, значение которого для каждой строки вычисляется из значений других столбцов той же строки.
Если это действительно так, вы можете использовать df.apply
, предоставив ему функцию, которая вычисляет значение для конкретной строки:
def flag_value(row):
if row.entity == 10 and row.value != 1000 and row.location == CA:
return "A"
elif row.entity != 10 and row.entity != 0 and row.value == 1000 and row.location == US:
return "C"
elif row.entity == 0 and row.value == 1000 and row.location == US:
return "B"
else:
return "Different case"
df['flag'] = df.apply(flag_value, axis=1)
Взгляните на этот связанный вопрос для получения дополнительной информации.
Если вы действительно хотите найти все столбцы, которые задают некоторое условие, обычный способ сделать это с фреймом данных Pandas — использовать df.loc
и индексацию:
only_a_cases = df.loc[df.entity == 10 & df.value != 1000 & df.location == "CA"]
# or:
only_a_cases = df.loc[lambda df: df.entity == 10 & df.value != 1000 & df.location == "CA"]
Спасибо, это выглядит интересно! Один вопрос - должен ли я делать это для каждой строки (поскольку d - это одна строка), так что все еще в цикле?