В настоящее время я работаю над проектом, в котором мне нужно выполнить условные замены в DataFrame Pandas. Я реализовал решение, но мне интересно, есть ли более эффективный способ добиться того же результата.
import pandas as pd
data = {
'Name': ['Alice', 'Bob', 'Charlie', 'David', 'Emma'],
'Age': [25, 30, 35, 40, 45],
'City': ['New York', 'Los Angeles', 'Chicago', 'Houston', 'Phoenix']
}
df_init = pd.DataFrame(data)
# Using `.loc`
df_init['Group'] = ['A', 'B', 'C', 'D', 'E']
df_init.loc[df_init.loc[
(df_init.City=='New York')
&(df_init.Name=='Alice')].index, 'City'] = 'Hamburg'
# Using method chaining
def _replace(dataframe):
dataframe.loc[dataframe.loc[
(dataframe.City=='New York')
&(dataframe.Name=='Alice')].index, 'City'] = 'Hamburg'
return dataframe
(df_init
.assign(Group=['A', 'B', 'C', 'D', 'E'])
.pipe(_replace)
)
В первом методе я использую метод .loc
, чтобы найти строку, в которой выполняются условия, а затем выполнить замену. Во втором подходе я использую цепочку методов с .assign
и .pipe
для достижения того же результата.
Мой вопрос: есть ли более эффективный способ заменить метод .loc
цепочкой методов в операциях Pandas DataFrame? Должен отметить, что я новичок в методах объединения мира панд.
Код
привести в состояние и использовать mask
func.
cond = df_init['City'].eq('New York') & df_init['Name'].eq('Alice')
out = df_init.assign(
Group = ['A', 'B', 'C', 'D', 'E'],
City=df_init['City'].mask(cond, 'Hamburg')
)
вне
Name Age City Group
0 Alice 25 Hamburg A
1 Bob 30 Los Angeles B
2 Charlie 35 Chicago C
3 David 40 Houston D
4 Emma 45 Phoenix E
Не изменяйте DataFrame при вызове pipe
. Я бы использовал маску с лямбдой/вызываемым объектом:
out = df_init.assign(Group=['A', 'B', 'C', 'D', 'E'],
City=lambda d: d['City'].mask(d['City'].eq('New York')&d['Name'].eq('Alice'), 'Hamburg')
Выход:
Name Age City
0 Alice 25 Hamburg
1 Bob 30 Los Angeles
2 Charlie 35 Chicago
3 David 40 Houston
4 Emma 45 Phoenix
Есть несколько различных вариантов, которые вы можете использовать, включая использование цепочки методов с помощью pipe
или вы можете использовать np.where
. Учитывая ваш вопрос, я проверил оба приведенных ниже варианта со временем:
Использование трубы:
def _replace(dataframe):
dataframe.loc[(dataframe.City=='New York') & (dataframe.Name=='Alice'), 'City'] = 'Hamburg'
return dataframe
def method_pipe(df):
return (df
.assign(Group=['A', 'B', 'C', 'D', 'E'])
.pipe(_replace)
)
НП.где:
def method_where(df):
return df.assign(
Group=['A', 'B', 'C', 'D', 'E'],
City=np.where((df['City'] == 'New York') & (df['Name'] == 'Alice'), 'Hamburg', df['City'])
)
Я протестировал их оба, и ниже показано время, затраченное на использование онлайн-компилятора Python Programiz:
{'loc': 0.0017023086547851562, 'pipe': 0.0009500980377197266, 'where': 0.0007925033569335938}
Знаете ли вы о функции pandas.DataFrame.where() (pandas.pydata.org/docs/reference/api/…)? Я чувствую, что это может решить вашу проблему, но я не уверен.