【问题标题】:Selecting rows with specified days in datetimeindex dataframe - Pandas在 datetimeindex 数据框中选择具有指定天数的行 - Pandas
【发布时间】:2015-11-23 19:37:30
【问题描述】:

我有一个带有 datetimeindex 的数据框。我只需要那些索引属于列表中指定天数的行,例如[1,2] 周一和周二。这在熊猫中是否可以在一行代码中实现。

【问题讨论】:

    标签: pandas dataframe datetimeindex


    【解决方案1】:

    你可以试试这个:

    In [3]: import pandas as pd
    In [4]: import numpy as np
    
    In [5]: index = pd.date_range('11/23/2015', end = '11/30/2015', freq='d')
    In [6]: df = pd.DataFrame(np.random.randn(len(index),2),columns=list('AB'),index=index)
    
    In [7]: df
    Out[7]:
                       A         B
    2015-11-23 -0.673626 -1.009921
    2015-11-24 -1.288852 -0.338795
    2015-11-25 -1.414042 -0.767050
    2015-11-26  0.018223 -0.726230
    2015-11-27 -1.288709 -1.144437
    2015-11-28  0.121093  1.396825
    2015-11-29 -0.791611 -1.014375
    2015-11-30  1.223220 -1.223499
    
    
    In [8]: df[np.in1d(df.index.dayofweek, [1, 2])]
    Out[8]:
                       A         B
    2015-11-24  0.116678 -0.715655
    2015-11-25 -1.494921  0.218176
    

    1 实际上是星期二。但如果需要,这应该很容易解决。

    之前的答案是在写这篇文章时发布的,作为比较:

    In [15]: %timeit df.loc[df.index.to_series().dt.dayofweek.isin([0,1]).values]
    100 loops, best of 3: 2.01 ms per loop
    
    In [16]: %timeit df[np.in1d(df.index.dayofweek, [0, 1])]
    1000 loops, best of 3: 393 µs per loop
    

    请注意,此比较是在我创建的测试 DF 上完成的,我不知道它如何必然扩展到更大的数据帧,尽管性能应该是一致的。

    【讨论】:

      【解决方案2】:

      IIUC 那么以下应该可以工作:

      df[df.index.to_series().dt.dayofweek.isin([0,1])]
      

      例子:

      In [9]:
      df = pd.DataFrame(index=pd.date_range(start=dt.datetime(2015,1,1), end = dt.datetime(2015,2,1)))
      df[df.index.to_series().dt.dayofweek.isin([0,1])]
      
      Out[9]:
      Empty DataFrame
      Columns: []
      Index: [2015-01-05 00:00:00, 2015-01-06 00:00:00, 2015-01-12 00:00:00, 2015-01-13 00:00:00, 2015-01-19 00:00:00, 2015-01-20 00:00:00, 2015-01-26 00:00:00, 2015-01-27 00:00:00]
      

      所以这会将DateTimeIndex 转换为Series,这样我们就可以调用isin 来测试成员资格,使用.dt.dayofweek 并传递0,1(这对应于星期一和星期二),我们使用布尔值mask 来屏蔽索引

      另一种方法是构造一个布尔掩码而不转换为Series

      In [12]:
      df[(df.index.dayofweek == 0) | (df.index.dayofweek == 1)]
      
      Out[12]:
      Empty DataFrame
      Columns: []
      Index: [2015-01-05 00:00:00, 2015-01-06 00:00:00, 2015-01-12 00:00:00, 2015-01-13 00:00:00, 2015-01-19 00:00:00, 2015-01-20 00:00:00, 2015-01-26 00:00:00, 2015-01-27 00:00:00]
      

      或者事实上这会起作用:

      In [13]:
      df[df.index.dayofweek < 2]
      
      Out[13]:
      Empty DataFrame
      Columns: []
      Index: [2015-01-05 00:00:00, 2015-01-06 00:00:00, 2015-01-12 00:00:00, 2015-01-13 00:00:00, 2015-01-19 00:00:00, 2015-01-20 00:00:00, 2015-01-26 00:00:00, 2015-01-27 00:00:00]
      

      时机

      In [14]:
      %timeit df[df.index.dayofweek < 2]
      %timeit df[np.in1d(df.index.dayofweek, [1, 2])]
      
      1000 loops, best of 3: 464 µs per loop
      1000 loops, best of 3: 521 µs per loop
      

      所以我的最后一个方法在这里比 np 方法稍微快一点

      【讨论】:

      • 谢谢:)。我想在您的第一个示例中执行类似操作,以便可以使用我拥有的列表,但 Pandas 0.14 没有 .dt 并且我目前对更新它有限制。我们可以在 0.14 中做同样的事情吗?
      • 其他方法应该可以工作,否则类似:df[df.index.to_series().apply(lambda x: x.dayofweek in([0,1]))] 可以工作,但对于大型 dfs 会很慢,因为这只是一个for 循环
      • 我最终使用了 df[np.in1d(df.index.dayofweek, [1, 2])],谢谢。
      猜你喜欢
      • 1970-01-01
      • 2019-07-10
      • 2018-10-15
      • 2018-12-04
      • 2020-10-06
      • 1970-01-01
      • 2013-04-02
      • 2012-08-10
      相关资源
      最近更新 更多