【问题标题】:Multi-index slicing (involving a time series / date range) does not work with DataFrame but does for Series多索引切片(涉及时间序列/日期范围)不适用于 DataFrame,但适用于 Series
【发布时间】:2019-01-26 05:43:50
【问题描述】:

为日期范围切片多索引 DataFrame 似乎不起作用(数据帧返回未切片),而对多索引系列执行相同的操作。

例如:

# Create a multi-indexed DataFrame with time series as 'inner' index
idx = pd.MultiIndex.from_product([['id1', 'id2', 'id3'], pd.date_range('2019-01-01', '2019-01-05')], names=['id', 'date'])
cols = ['colA', 'colB']
example_df = pd.DataFrame(np.ones(30).reshape(15, 2), idx, cols)

example_df 看起来像:

                colA    colB
id  date        
id1 2019-01-01  1.0     1.0
    2019-01-02  1.0     1.0
    2019-01-03  1.0     1.0
    2019-01-04  1.0     1.0
    2019-01-05  1.0     1.0
id2 2019-01-01  1.0     1.0
    2019-01-02  1.0     1.0
    2019-01-03  1.0     1.0
    2019-01-04  1.0     1.0
    2019-01-05  1.0     1.0
id3 2019-01-01  1.0     1.0
    2019-01-02  1.0     1.0
    2019-01-03  1.0     1.0
    2019-01-04  1.0     1.0
    2019-01-05  1.0     1.0

尝试对内部“日期”索引级别进行切片,只是简单地产生上面的 DataFrame 不变。

# Get all records for 3rd January 2019 onward, for all ids
idx = pd.IndexSlice
example_df.loc[idx[:, '2019-01-3':]] # yields example_df unchanged

想要的结果是:

                colA    colB
id  date        
id1 2019-01-03  1.0     1.0
    2019-01-04  1.0     1.0
    2019-01-05  1.0     1.0
id2 2019-01-03  1.0     1.0
    2019-01-04  1.0     1.0
    2019-01-05  1.0     1.0
id3 2019-01-03  1.0     1.0
    2019-01-04  1.0     1.0
    2019-01-05  1.0     1.0

奇怪的是,对 Series 进行切片会产生预期的结果

# Perform same slice but just for colA
example_df.colA.loc[idx[:, '2019-01-3':]]    

这会产生预期的结果

id   date      
id1  2019-01-03    1.0
     2019-01-04    1.0
     2019-01-05    1.0
id2  2019-01-03    1.0
     2019-01-04    1.0
     2019-01-05    1.0
id3  2019-01-03    1.0
     2019-01-04    1.0
     2019-01-05    1.0   

我正在使用 pandas 0.23.1。

感谢任何关于如何让切片适用于 DataFrame 版本的意见。我知道我可以在内部日期索引上使用布尔掩码实现相同的结果,即

from datetime import datetime
inner_mask = example_df.index.get_level_values(1) >= datetime(2019, 1, 3)
example_df[inner_mask]

...但我很想知道为什么这种切片方法不起作用(尤其是当它适用于系列版本时)。谢谢。

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    您需要在DataFrame.loc 的第二个位置指定列colA

    print(example_df.loc[idx[:, '2019-01-3':], 'colA'])
    id   date      
    id1  2019-01-03    1.0
         2019-01-04    1.0
         2019-01-05    1.0
    id2  2019-01-03    1.0
         2019-01-04    1.0
         2019-01-05    1.0
    id3  2019-01-03    1.0
         2019-01-04    1.0
         2019-01-05    1.0
    Name: colA, dtype: float64
    

    如果想要一个列DataFrame 使用一个元素列表:

    print(example_df.loc[idx[:, '2019-01-3':], ['colA']])
                    colA
    id  date            
    id1 2019-01-03   1.0
        2019-01-04   1.0
        2019-01-05   1.0
    id2 2019-01-03   1.0
        2019-01-04   1.0
        2019-01-05   1.0
    id3 2019-01-03   1.0
        2019-01-04   1.0
        2019-01-05   1.0
    

    与布尔掩码相同的原理:

    print(example_df.loc[inner_mask, 'colA'])
    id   date      
    id1  2019-01-03    1.0
         2019-01-04    1.0
         2019-01-05    1.0
    id2  2019-01-03    1.0
         2019-01-04    1.0
         2019-01-05    1.0
    id3  2019-01-03    1.0
         2019-01-04    1.0
         2019-01-05    1.0
    Name: colA, dtype: float64
    
    print(example_df.loc[inner_mask, ['colA']])
                    colA
    id  date            
    id1 2019-01-03   1.0
        2019-01-04   1.0
        2019-01-05   1.0
    id2 2019-01-03   1.0
        2019-01-04   1.0
        2019-01-05   1.0
    id3 2019-01-03   1.0
        2019-01-04   1.0
        2019-01-05   1.0
    

    对于切片所有列使用::

    print(example_df.loc[idx[:, '2019-01-3':], :])
                    colA  colB
    id  date                  
    id1 2019-01-03   1.0   1.0
        2019-01-04   1.0   1.0
        2019-01-05   1.0   1.0
    id2 2019-01-03   1.0   1.0
        2019-01-04   1.0   1.0
        2019-01-05   1.0   1.0
    id3 2019-01-03   1.0   1.0
        2019-01-04   1.0   1.0
        2019-01-05   1.0   1.0
    

    【讨论】:

    • 谢谢耶兹瑞尔。使用 example_df.loc[idx[:, '2019-01-3':], ] 返回所有列(这是我想要的)。我想知道为什么我们需要有效地将None 指定到DataFrame.loc 的第二个位置,以返回所有列?
    • 所有列最好使用: - example_df.loc[idx[:, '2019-01-3':], :]
    猜你喜欢
    • 1970-01-01
    • 2023-02-08
    • 2021-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-18
    • 1970-01-01
    • 2020-08-07
    相关资源
    最近更新 更多