使用.loc访问器的pandas datetime索引的布尔掩码

时间:2018-04-08 15:39:47

标签: python performance pandas datetime

Asumme以下玩具代码:

import numpy as np
import pandas as pd
rng = pd.date_range('1/1/2011', periods=72, freq='H')
avec = np.random.rand(len(rng))
bvec = np.random.rand(len(rng))
df = pd.DataFrame({"A":avec,"B":bvec}, index=rng)

我现在可以用

选择时间间隔的一部分
df.loc["2011-01-02",:]

有没有办法有效地访问与结果切片相对应的布尔掩码,即:

array([False, False, False, False, False, False, False, False, False,
       False, False, False, False, False, False, False, False, False,
       False, False, False, False, False, False,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True, False, False, False, False, False, False,
       False, False, False, False, False, False, False, False, False,
       False, False, False, False, False, False, False, False, False], dtype=bool)

我已尝试过an earlier stackoverflow answer中的建议,但df.index.date需要很长时间才能运行我的数据集......

3 个答案:

答案 0 :(得分:6)

如果性能是重要的链2布尔掩码:

(df.index >= "2011-01-02") & (df.index < "2011-01-03")

答案 1 :(得分:0)

IIUC,你可以这样做:

df.index.isin(df.loc["2011-01-02",:].index)

array([False, False, False, False, False, False, False, False, False,
   False, False, False, False, False, False, False, False, False,
   False, False, False, False, False, False,  True,  True,  True,
    True,  True,  True,  True,  True,  True,  True,  True,  True,
    True,  True,  True,  True,  True,  True,  True,  True,  True,
    True,  True,  True, False, False, False, False, False, False,
   False, False, False, False, False, False, False, False, False,
   False, False, False, False, False, False, False, False, False], dtype=bool)

然而,@ jezrael的答案更快。我把它作为替代解决方案。这提供的唯一便利是,如果您想按名称而不是日期字符串引用切片数据框,例如:

# named slice of your original dataframe:
sliced_df = df.loc["2011-01-02",:]
# get boolean array:
df.index.isin(sliced_df.index)

答案 2 :(得分:0)

您可以提取索引的numpy表示形式并与np.datetime64对象进行比较:

import numpy as np
from datetime import datetime

(df.index.values >= np.datetime64(datetime.strptime("2011-01-02", '%Y-%m-%d'))) & \
(df.index.values < np.datetime64(datetime.strptime("2011-01-03", '%Y-%m-%d')))

关于行为的说明

上述解决方案特定于问题中的查询。正如@Jeff指出的那样,datetime的字符串表示使用了部分索引。因此,只应在特定情况下使用numpy

有关详细信息,请参阅pandas索引上的datetime documentation

效果基准

df = pd.concat([df]*1000)

%timeit (df.index >= "2011-01-02") & (df.index < "2011-01-03")

%timeit (df.index.values >= np.datetime64(datetime.strptime("2011-01-02", '%Y-%m-%d'))) & \
        (df.index.values < np.datetime64(datetime.strptime("2011-01-03", '%Y-%m-%d')))

assert ((df.index >= "2011-01-02") & (df.index < "2011-01-03") == \
        (df.index.values >= np.datetime64(datetime.strptime("2011-01-02", '%Y-%m-%d'))) & \
        (df.index.values < np.datetime64(datetime.strptime("2011-01-03", '%Y-%m-%d')))).all()

# 1.21 ms ± 23 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
# 527 µs ± 11.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)