@DSM có IMO câu trả lời đúng, nhưng tôi muốn chia sẻ sự khái quát và tối ưu hóa của tôi cho câu hỏi: Nhiều cột thành từng nhóm và có nhiều cột giá trị:
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],
}
)
... cho ...
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
Trong trường hợp tổng quát này, chúng tôi muốn nhóm theo category
và name
và chỉ hàm ý trên value
.
Điều này có thể được giải quyết như sau:
df['value'] = df.groupby(['category', 'name'])['value']\
.transform(lambda x: x.fillna(x.mean()))
Lưu ý danh sách cột trong mệnh đề từng nhóm và chúng tôi chọn value
cột ngay sau từng nhóm. Điều này làm cho phép biến đổi chỉ được chạy trên cột cụ thể đó. Bạn có thể thêm nó vào cuối, nhưng sau đó bạn sẽ chạy nó cho tất cả các cột chỉ để loại bỏ tất cả trừ một cột đo lường ở cuối. Một công cụ lập kế hoạch truy vấn SQL chuẩn có thể đã tối ưu hóa điều này, nhưng gấu trúc (0.19.2) dường như không làm được điều này.
Kiểm tra hiệu suất bằng cách tăng tập dữ liệu bằng cách thực hiện ...
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
... xác nhận rằng điều này làm tăng tốc độ tương ứng với số cột bạn không phải áp dụng:
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)
Lưu ý cuối cùng, bạn có thể tổng quát hóa hơn nữa nếu bạn muốn áp dụng nhiều hơn một cột, nhưng không phải tất cả:
df[['value', 'other_value']] = df.groupby(['category', 'name'])['value', 'other_value']\
.transform(lambda x: x.fillna(x.mean()))
groupby
phần. Có quá nhiều thứ để nhớ, nhưng bạn chọn các quy tắc như "chuyển đổi dành cho các hoạt động của mỗi nhóm mà bạn muốn lập chỉ mục giống như khung ban đầu", v.v.