@DSM має правильну відповідь IMO, але я хотів би поділитися своїм узагальненням та оптимізацією питання: Кілька стовпців для групування та наявність кількох стовпців значень:
df = pd.DataFrame(
{
'category': ['X', 'X', 'X', 'X', 'X', 'X', 'Y', 'Y', 'Y'],
'name': ['A','A', 'B','B','B','B', 'C','C','C'],
'other_value': [10, np.nan, np.nan, 20, 30, 10, 30, np.nan, 30],
'value': [1, np.nan, np.nan, 2, 3, 1, 3, np.nan, 3],
}
)
... дає ...
category name other_value value
0 X A 10.0 1.0
1 X A NaN NaN
2 X B NaN NaN
3 X B 20.0 2.0
4 X B 30.0 3.0
5 X B 10.0 1.0
6 Y C 30.0 3.0
7 Y C NaN NaN
8 Y C 30.0 3.0
У цьому узагальненому випадку ми хотіли б згрупувати за category
і name
, і вказувати лише на value
.
Це можна вирішити наступним чином:
df['value'] = df.groupby(['category', 'name'])['value']\
.transform(lambda x: x.fillna(x.mean()))
Зверніть увагу на список стовпців у реченні про групу та про те, що ми вибираємо value
стовпець відразу після групи. Це робить перетворення запущеним лише у цьому конкретному стовпці. Ви можете додати його до кінця, але тоді ви будете запускати його для всіх стовпців, лише щоб викинути всі, крім одного стовпчика міри в кінці. Стандартний планувальник запитів SQL міг би це змогти оптимізувати, але pandas (0.19.2), схоже, цього не робить.
Тест продуктивності за рахунок збільшення набору даних, роблячи ...
big_df = None
for _ in range(10000):
if big_df is None:
big_df = df.copy()
else:
big_df = pd.concat([big_df, df])
df = big_df
... підтверджує, що це збільшує швидкість пропорційно кількості стовпців, які вам не потрібно вводити:
import pandas as pd
from datetime import datetime
def generate_data():
...
t = datetime.now()
df = generate_data()
df['value'] = df.groupby(['category', 'name'])['value']\
.transform(lambda x: x.fillna(x.mean()))
print(datetime.now()-t)
t = datetime.now()
df = generate_data()
df["value"] = df.groupby(['category', 'name'])\
.transform(lambda x: x.fillna(x.mean()))['value']
print(datetime.now()-t)
На завершальній ноті ви можете узагальнити ще більше, якщо хочете вписати більше одного стовпця, але не всіх:
df[['value', 'other_value']] = df.groupby(['category', 'name'])['value', 'other_value']\
.transform(lambda x: x.fillna(x.mean()))
groupby
розділ висвітлений . Забагато речей, щоб пам’ятати, але ви підбираєте правила на кшталт "перетворення - це для групових операцій, які ви хочете проіндексувати, як оригінальний кадр" тощо.