首页 > 解决方案 > Python Pandas DataFrame:按带有字符串时间戳列表的时间戳列过滤

问题描述

示例设置:

import pandas as pd
df = pd.DataFrame(
    data={'ts':
          [
                '2008-11-05 07:45:23.100',
                '2008-11-17 06:53:25.150',
                '2008-12-02 07:36:18.643',
                '2008-12-15 07:36:24.837',
                '2009-01-06 07:03:47.387',
          ], 
          'val': range(5)})

df.ts = pd.to_datetime(df.ts)

df.set_index('ts', drop=False, inplace=True)

df


                        | ts                      | val
2008-11-05 07:45:23.100 | 2008-11-05 07:45:23.100 | 0
2008-11-17 06:53:25.150 | 2008-11-17 06:53:25.150 | 1
2008-12-02 07:36:18.643 | 2008-12-02 07:36:18.643 | 2
2008-12-15 07:36:24.837 | 2008-12-15 07:36:24.837 | 3
2009-01-06 07:03:47.387 | 2009-01-06 07:03:47.387 | 4

虽然索引是 pd.Timestamp 类型,但我可以使用时间戳的字符串表示来过滤它。例如:

df.loc['2008-11-05']

                        | ts                      | val
2008-11-05 07:45:23.100 | 2008-11-05 07:45:23.100 | 0

此外,pandas 带有一个非常方便的功能,当我的过滤器模糊时,它会返回理想的结果。例如:

df.loc['2008-12']
                        | ts                      | val
2008-12-02 07:36:18.643 | 2008-12-02 07:36:18.643 | 2
2008-12-15 07:36:24.837 | 2008-12-15 07:36:24.837 | 3

我的第一个问题是,如何使用字符串时间戳列表过滤 df?例如,如果我运行下面的代码

df.loc[['2008-11-05','2008-12']]

,我想要得到的结果是

                        | ts                      | val
2008-11-05 07:45:23.100 | 2008-11-05 07:45:23.100 | 0
2008-12-02 07:36:18.643 | 2008-12-02 07:36:18.643 | 2
2008-12-15 07:36:24.837 | 2008-12-15 07:36:24.837 | 3

,但实际上我收到以下错误:

KeyError: "None of [Index(['2008-11-05', '2008-12'], dtype='object', name='ts')] are in the [index]"

我的第二个问题是,我可以对常规列执行类似的过滤逻辑吗?即,如果我不设置ts为索引而是ts直接使用字符串过滤器过滤列。

-------------------- 跟进 2019-9-10 10:00 --------------------

非常感谢以下所有答案。不知道pd.Series.str.startswith能不能支持tuple多个字符串的输入,还是pd.Series.str.contains能支持'|'. 学到了新技能!

我认为所有基于使用的方法astype(str)对我来说都有一个主要缺点:在美国,人们使用各种日期时间格式。除了'2008-11-05',我公司常用的还有'2008-11-5', '11/05/2008', '11/5/2008', '20081105', '05nov2008'如果我使用基于字符串的方法,一切都会失败。

现在我仍然必须坚持以下方法,它要求列作为索引并且看起来效率不高(我没有分析过),但应该足够健壮。我不明白为什么熊猫本身不支持它。

L = ['5nov2008','2008/12']
pd.concat([df.loc[val] for val in L]).drop_duplicates()

                        | ts                      | val
2008-11-05 07:45:23.100 | 2008-11-05 07:45:23.100 | 0
2008-12-02 07:36:18.643 | 2008-12-02 07:36:18.643 | 2
2008-12-15 07:36:24.837 | 2008-12-15 07:36:24.837 | 3

标签: pythonpandasdataframe

解决方案


这应该开始为你..

>>> df
                       ts  val
0 2008-11-05 07:45:23.100    0
1 2008-11-17 06:53:25.150    1
2 2008-12-02 07:36:18.643    2
3 2008-12-15 07:36:24.837    3
4 2009-01-06 07:03:47.387    4

结果:

>>> df[df.apply(lambda row: row.astype(str).str.contains('2008-11-05')).any(axis=1)]
                       ts  val
0 2008-11-05 07:45:23.100    0

或者 ..

>>> df
                                             ts  val
ts
2008-11-05 07:45:23.100 2008-11-05 07:45:23.100    0
2008-11-17 06:53:25.150 2008-11-17 06:53:25.150    1
2008-12-02 07:36:18.643 2008-12-02 07:36:18.643    2
2008-12-15 07:36:24.837 2008-12-15 07:36:24.837    3
2009-01-06 07:03:47.387 2009-01-06 07:03:47.387    4

结果:

>>> df[df.apply(lambda row: row.astype(str).str.contains('2008-11-05')).any(axis=1)]
                                             ts  val
ts
2008-11-05 07:45:23.100 2008-11-05 07:45:23.100    0

寻找多个值。

>>> df[df.apply(lambda row: row.astype(str).str.contains('2008-11-05|2008-12')).any(axis=1)]
                                             ts  val
ts
2008-11-05 07:45:23.100 2008-11-05 07:45:23.100    0
2008-12-02 07:36:18.643 2008-12-02 07:36:18.643    2
2008-12-15 07:36:24.837 2008-12-15 07:36:24.837    3

推荐阅读