我一直在追踪一个奇怪的错误,或者至少是近期熊猫版本的行为改变(不确定何时发生了变化,有时在0.16.2之间 - 它工作正常 - 和0.19。 2)。
基本上,我想要平滑DataFrame
中的几列,但我有MultiIndex
的日期和ID,并且应在取消堆叠ID后应用平滑(即所有ID ,对于选定的列)。如果我在卸载后执行stack('id')
,没问题,列的顺序保持不变。但是,如果在df_fat.rolling(...).mean()
之后完成取消堆栈,则列将按字母顺序排序。此外,将平滑后的列分配回原始帧会将结果分配给错误的列,在我们的情况下会产生非常糟糕的结果。
现在,我知道对索引(和列)进行排序是明智的,但我很惊讶最后一个单元格([5]中的赋值)显然是错误的,甚至没有大熊猫的抱怨。这是熊猫的错误吗?至少会有警告吗?
总结一下,我看到两个问题:
.rolling().func
更改了列顺序:它按字母顺序对它们进行排序。slice = df
不尊重列名称(如.join
所示) - 只需插入值。这是一个可重复的例子:
In[1]:
import numpy as np
import pandas as pd
import io
str = """t,id,x,foo,bar
2012-01-01,A,0,100,1
2015-10-27,B,1,200,2
2015-11-15,B,2,300,3
"""
df = pd.read_csv(io.StringIO(str), parse_dates=[0], index_col=[0,1]).sort_index()
df
Out[1]:
x foo bar
t id
2012-01-01 A 0 100 1
2015-10-27 B 1 200 2
2015-11-15 B 2 300 3
现在,我想要平滑两列foo
和bar
。首先,做一个'胖' df因此可以使用.rolling().mean()
轻松完成平滑。 (还要注意null_index
以保留NaN在原始位置的位置:
In[2]:
feat_names = ['foo', 'bar']
df_fat = df[feat_names].unstack('id')
null_index = df_fat.isnull()
df_fat
Out[2]:
foo bar
id A B A B
t
2012-01-01 100.0 NaN 1.0 NaN
2015-10-27 NaN 200.0 NaN 2.0
2015-11-15 NaN 300.0 NaN 3.0
到目前为止,没问题。实际上,对于所选列,堆叠会产生原始df:
In[3]:
df_fat.stack('id')
Out[3]:
foo bar
t id
2012-01-01 A 100.0 1.0
2015-10-27 B 200.0 2.0
2015-11-15 B 300.0 3.0
现在,让我们进行平滑处理:
In[4]:
df_fat = df_fat.rolling(center=False, window=2, min_periods=1).mean()
df_fat.stack('id')
Out[4]:
bar foo
t id
2012-01-01 A 1.0 100.0
2015-10-27 A 1.0 100.0
B 2.0 200.0
2015-11-15 B 2.5 250.0
请注意列的排序方式。然后,当试图分配回原始版本时,所有地狱都会松动,列值将被插入"不考虑列名:
In[5]:
df_fat[null_index] = np.NaN
df[feat_names] = df_fat.stack('id')
df
Out[5]:
x foo bar
t id
2012-01-01 A 0 1.0 100.0
2015-10-27 B 1 2.0 200.0
2015-11-15 B 2 2.5 250.0
请注意,明确重新排序分配右侧的列会产生预期结果:
In[6]:
df_fat[null_index] = np.NaN
df[feat_names] = df_fat.stack('id')[feat_names]
df
Out[6]:
x foo bar
t id
2012-01-01 A 0 100.0 1.0
2015-10-27 B 1 200.0 2.0
2015-11-15 B 2 250.0 2.5