使用 apply 降低多索引 pandas 数据框的维度
Reducing dimensionality of multiindex pandas dataframe using apply
我有以下数据框:
df = pd.DataFrame({('psl', 't1'): {'fiat': 36.389809173765507,
'mazda': 18.139242981049016,
'opel': 0.97626485600703961,
'toyota': 74.464422292108878},
('psl', 't2'): {'fiat': 35.423004380643462,
'mazda': 24.269803148695079,
'opel': 1.0170540474994665,
'toyota': 60.389948228586832},
('psv', 't1'): {'fiat': 35.836800462163097,
'mazda': 15.893295606055901,
'opel': 0.78744853046848606,
'toyota': 74.054850828062271},
('psv', 't2'): {'fiat': 34.379812557124815,
'mazda': 23.202587247335682,
'opel': 0.80191294532382451,
'toyota': 58.735083244244322}})
看起来像这样:
我希望将其从多索引缩减为普通索引。我希望通过应用一个使用 t1 和 t2 值的函数并仅返回一个值来实现这一点,这将导致有两列:psl 和 psv。
我已经成功地将它分组并应用了一个函数:
df.groupby(level=0, axis=1).agg(np.mean)
这非常接近我想要的,除了我不想应用 np.mean,而是一个自定义函数。特别是百分比变化函数。
我的最终目标是能够做这样的事情:
df.groupby(level=0, axis=1).apply(lambda t1, t2: (t2-t1)/t1)
其中returns这个错误:
TypeError: <lambda>() missing 1 required positional argument: 't2'
我也试过这个:
df.apply(lambda x: x[x.name].apply(lambda x: x['t1']/x['t2']))
反过来 returns:
KeyError: (('psl', 't1'), 'occurred at index (psl, t1)')
能否请您尽最大努力对答案的每一部分进行详尽的解释,以便我更好地理解 pandas 的工作原理。
不容易。使用自定义函数 squeeze
for Series
and xs
for select MultiIndex
in columns:
def f(x):
t2 = x.xs('t2', axis=1, level=1)
t1 = x.xs('t1', axis=1, level=1)
a = (t2-t1)/t1
#print (a)
return (a.squeeze())
df1 = df.groupby(level=0, axis=1).agg(f)
print (df1)
psl psv
fiat -0.026568 -0.040656
mazda 0.337972 0.459898
opel 0.041781 0.018369
toyota -0.189009 -0.206871
可以使用 lambda 函数,但是重复代码真的很糟糕:
df1 = df.groupby(level=0, axis=1)
.agg(lambda x: ((x.xs('t2', axis=1, level=1)-x.xs('t1', axis=1, level=1))/
x.xs('t1', axis=1, level=1)).squeeze())
我有以下数据框:
df = pd.DataFrame({('psl', 't1'): {'fiat': 36.389809173765507,
'mazda': 18.139242981049016,
'opel': 0.97626485600703961,
'toyota': 74.464422292108878},
('psl', 't2'): {'fiat': 35.423004380643462,
'mazda': 24.269803148695079,
'opel': 1.0170540474994665,
'toyota': 60.389948228586832},
('psv', 't1'): {'fiat': 35.836800462163097,
'mazda': 15.893295606055901,
'opel': 0.78744853046848606,
'toyota': 74.054850828062271},
('psv', 't2'): {'fiat': 34.379812557124815,
'mazda': 23.202587247335682,
'opel': 0.80191294532382451,
'toyota': 58.735083244244322}})
看起来像这样:
我希望将其从多索引缩减为普通索引。我希望通过应用一个使用 t1 和 t2 值的函数并仅返回一个值来实现这一点,这将导致有两列:psl 和 psv。
我已经成功地将它分组并应用了一个函数:
df.groupby(level=0, axis=1).agg(np.mean)
这非常接近我想要的,除了我不想应用 np.mean,而是一个自定义函数。特别是百分比变化函数。
我的最终目标是能够做这样的事情:
df.groupby(level=0, axis=1).apply(lambda t1, t2: (t2-t1)/t1)
其中returns这个错误:
TypeError: <lambda>() missing 1 required positional argument: 't2'
我也试过这个:
df.apply(lambda x: x[x.name].apply(lambda x: x['t1']/x['t2']))
反过来 returns:
KeyError: (('psl', 't1'), 'occurred at index (psl, t1)')
能否请您尽最大努力对答案的每一部分进行详尽的解释,以便我更好地理解 pandas 的工作原理。
不容易。使用自定义函数 squeeze
for Series
and xs
for select MultiIndex
in columns:
def f(x):
t2 = x.xs('t2', axis=1, level=1)
t1 = x.xs('t1', axis=1, level=1)
a = (t2-t1)/t1
#print (a)
return (a.squeeze())
df1 = df.groupby(level=0, axis=1).agg(f)
print (df1)
psl psv
fiat -0.026568 -0.040656
mazda 0.337972 0.459898
opel 0.041781 0.018369
toyota -0.189009 -0.206871
可以使用 lambda 函数,但是重复代码真的很糟糕:
df1 = df.groupby(level=0, axis=1)
.agg(lambda x: ((x.xs('t2', axis=1, level=1)-x.xs('t1', axis=1, level=1))/
x.xs('t1', axis=1, level=1)).squeeze())