我有一只熊猫
DataFrame
:
import pandas as pd
df = pd.DataFrame({
"commodity":["Potatos","Potatos","Apples","Apples","Apples"],
"amount":[1,2,3,4,None],
"price":[4,5,6,7,8],
"attr1":[None,1,None,"foo","bar"],
})
(实际上,我有无数不同类型的列,例如
attr1
)。
我需要通过
commodity
总结框架,保持 first 非空 attr1
(和 last 非空 attr2
)。
这是我现在的做法:
df["cost"] = df.amount * df.price
def first(se):
"Get the first non-None element of the Series"
assert isinstance(se, pd.Series)
se = se.dropna()
if se.empty:
return None
return se.iloc[0]
summary = df.groupby("commodity").agg({"amount":sum, "cost":sum, "attr1":first})
df.drop(columns=["cost"], inplace=True)
summary["price"] = summary.cost / summary.amount
summary.drop(columns=["cost"], inplace=True)
columns = list(df.columns)
columns.remove("commodity")
summary = summary[columns]
summary
amount price attr1
commodity
Apples 7.0 6.571429 foo
Potatos 3.0 4.666667 1
这实现了我想要的功能,但是功能
first
似乎昂贵得难以忍受(正如预期)。
我想知道这是否可以更有效地完成。
也许你可以使用
.notna()
+ .idxmax()
:
x = df.groupby("commodity").agg(
{"amount": "sum", "attr1": lambda s: s.loc[s.notna().idxmax()]}
)
print(x)
打印:
amount attr1
commodity
Apples 7.0 foo
Potatos 3.0 1
或者:
Series.first_valid_index()
:
x = df.groupby("commodity").agg(
{"amount": "sum", "attr1": lambda s: s.loc[s.first_valid_index()]}
)
print(x)