熊猫:从MultiIndex中的日期中选择

时间:2015-04-05 15:07:36

标签: python pandas

假设我有MultiIndex系列

date        foo
2006-01-01  1         12931926.310
            3         11084049.460
            5         10812205.359
            7          9031510.239
            9          5324054.903
2007-01-01  1         11086082.624
            3         12028419.560
            5         11957253.031
            7         10643307.061
            9          6034854.915

如果它不是MultiIndex,我可以选择年2007df.loc['2007']的那些。我怎么在这里这样做?我的自然猜测是df.loc['2007', :],但这给了我一个空的Series([], name: FINLWT21, dtype: float64)

终极目标

最后,我也有兴趣用2007替换年份2007的不同日期的所有行。

也就是说,我的预期输出是

date        foo
2006-01-01  1         11086082.624
            3         12028419.560
            5         11957253.031
            7         10643307.061
            9          6034854.915
2007-01-01  1         11086082.624
            3         12028419.560
            5         11957253.031
            7         10643307.061
            9          6034854.915

我尝试实施@ unutbu的解决方案,但

mySeries.loc[dateIndex.year != 2007] = mySeries.loc[dateIndex.year == 2007]

自然会将值(由于RHS上不存在)设置为NaN。通常,这些问题由

修复
mySeries.loc[dateIndex.year != 2007] = mySeries.loc[dateIndex.year == 2007].values

,但鉴于我在左侧有10个值(在我的真实数据集中有更多值),但在右侧只有5,我得到了

ValueError: cannot set using a list-like indexer with a different length than the value

现在我想到的唯一选择是迭代第一个索引,然后对每个子组使用上一个命令,但这似乎不是最有效的解决方案。

2 个答案:

答案 0 :(得分:4)

鉴于系列

In [207]: series
Out[212]: 
date        foo
2006-01-01  1      12931926.310
            3      11084049.460
            5      10812205.359
            7       9031510.239
            9       5324054.903
2007-01-01  1      11086082.624
            3      12028419.560
            5      11957253.031
            7      10643307.061
            9       6034854.915
Name: val, dtype: float64

您可以使用

提取date索引
dateindex = series.index.get_level_values('date')
# Ensure the dateindex is a DatetimeIndex (as opposed to a plain Index)
dateindex = pd.DatetimeIndex(dateindex)

现在可以选择年份等于2007的行 布尔条件:

# select rows where year equals 2007
series2007 = series.loc[dateindex.year == 2007]

如果foo值在每个日期以相同的顺序循环显示相同的值, 然后你可以用2007年的

替换系列中的所有值
N = len(series)/len(series2007)
series[:] = np.tile(series.loc[dateindex.year == 2007].values, N)

使用np.tile.values的一个优点是它可以相对快速地生成所需的值数组。 (可能的)缺点是这忽略了索引,因此它依赖于foo值在每个日期以相同顺序循环相同值的假设。

更强大(但更慢)的方式是使用连接:

df = series.reset_index('date')
df2007 = df.loc[dateindex.year==2007]
df = df.join(df2007, rsuffix='_2007')
df = df[['date', 'val_2007']]
df = df.set_index(['date'], append=True)
df = df.swaplevel(0,1).sort_index()     

产量

In [304]: df.swaplevel(0,1).sort_index()
Out[304]: 
                    val_2007
date       foo              
2006-01-01 1    11086082.624
           3    12028419.560
           5    11957253.031
           7    10643307.061
           9     6034854.915
2007-01-01 1    11086082.624
           3    12028419.560
           5    11957253.031
           7    10643307.061
           9     6034854.915
2008-01-01 1    11086082.624
           3    12028419.560
           5    11957253.031
           7    10643307.061
           9     6034854.915

答案 1 :(得分:0)

要从所需年份的MultiIndex中选择值(例如2007),您可以使用:

target_year = 2007
df[[ts.year == target_year for ts in df.index.get_level_values(0)]]

如果日期索引不是时间戳的形式,则需要转换它:

df[[pd.Timestamp(ts).year == target_year for ts in df.index.get_level_values(0)]]
相关问题