Pandas DataFrame获取符合特定条件的行

3

我有一个Pandas数据框,需要从中获取所有索引符合特定条件的行。该数据框具有多重索引,我需要第一个索引(即TimeStamp)在特定范围内的行。多重索引的第一级是日期时间对象的系列。以下代码可用于检查月份是否等于5:

```python df.loc[(df.index.get_level_values('TimeStamp').month == 5)] ```
compare[compare.index.get_level_values(0).month == 5]

但是当我修改代码以检查值在某个数组中的行时

compare[compare.index.get_level_values(0).month in [5, 6, 7]]

我遇到了错误

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

我尝试使用df.loc获取值。

compare.loc[compare.index.get_level_values(0).month in [5, 6, 7]]

但是这会导致相同的错误。
我还尝试使用 isin 方法。
compare[compare.index.get_level_values(0).month.isin([5, 6, 7])]

但是这会导致以下属性错误:
AttributeError: 'numpy.ndarray' object has no attribute 'isin'

如何获取DataFrame中索引满足特定条件的行?


你能发布一下 print(compare.index.get_level_values(0)[:5]) 的输出吗?还有你使用的 Pandas 版本是多少? - MaxU - stand with Ukraine
DatetimeIndex(['2016-01-04 01:40:00', '2016-01-04 02:00:00', '2016-01-04 02:10:00', '2016-01-04 02:30:00', '2016-01-04 02:40:00'], dtype='datetime64[ns]', name=u'TTimeStamp', freq=None) 是我从 print 语句中得到的输出。我正在使用 Pandas 0.20.3 版本。 - victor
请看我的回答中的更新 - 我无法重现你的错误...我正在使用Pandas 0.20.1。 - MaxU - stand with Ukraine
1个回答

3

试试这个:

compare[compare.index.get_level_values(0).month.isin([5, 6, 7])]

PS 这适用于 Pandas 版本 0.18.1 及以上

演示:

In [45]: import pandas_datareader.data as web

In [46]: df = web.DataReader('AAPL', 'google', '2017-06-01')

In [48]: df = df.assign(i2=np.arange(len(df))).set_index('i2', append=True)

In [49]: df
Out[49]:
                 Open    High     Low   Close    Volume
Date       i2
2017-06-01 0   153.17  153.33  152.22  153.18  16404088
2017-06-02 1   153.58  155.45  152.89  155.45  27770715
2017-06-05 2   154.34  154.45  153.46  153.93  25331662
2017-06-06 3   153.90  155.81  153.78  154.45  26624926
2017-06-07 4   155.02  155.98  154.48  155.37  21069647
2017-06-08 5   155.25  155.54  154.40  154.99  21250798
2017-06-09 6   155.19  155.19  146.02  148.98  64882657
2017-06-12 7   145.74  146.09  142.51  145.42  72307330
2017-06-13 8   147.16  147.45  145.15  146.59  34165445
2017-06-14 9   147.50  147.50  143.84  145.16  31531232
...               ...     ...     ...     ...       ...
2017-07-31 41  149.90  150.33  148.13  148.73  19845920
2017-08-01 42  149.10  150.22  148.41  150.05  35368645
2017-08-02 43  159.28  159.75  156.16  157.14  69936800
2017-08-03 44  157.05  157.21  155.02  155.57  27097296
2017-08-04 45  156.07  157.40  155.69  156.39  20559852
2017-08-07 46  157.06  158.92  156.67  158.81  21870321
2017-08-08 47  158.60  161.83  158.27  160.08  36205896
2017-08-09 48  159.26  161.27  159.11  161.06  26131530
2017-08-10 49  159.90  160.00  154.63  155.32  40804273
2017-08-11 50  156.60  158.57  156.07  157.48  26180743

[51 rows x 5 columns]

In [50]: df[df.index.get_level_values(0).month.isin([5,8])]
Out[50]:
                 Open    High     Low   Close    Volume
Date       i2
2017-08-01 42  149.10  150.22  148.41  150.05  35368645
2017-08-02 43  159.28  159.75  156.16  157.14  69936800
2017-08-03 44  157.05  157.21  155.02  155.57  27097296
2017-08-04 45  156.07  157.40  155.69  156.39  20559852
2017-08-07 46  157.06  158.92  156.67  158.81  21870321
2017-08-08 47  158.60  161.83  158.27  160.08  36205896
2017-08-09 48  159.26  161.27  159.11  161.06  26131530
2017-08-10 49  159.90  160.00  154.63  155.32  40804273
2017-08-11 50  156.60  158.57  156.07  157.48  26180743

更新:测试您的索引值:

In [56]: i = pd.DatetimeIndex(['2016-01-04 01:40:00', '2016-01-04 02:00:00', '2016-01-04 02:10:00', '2016-01-04 02:30:00', '2016-01-04 02:4
    ...: 0:00'], dtype='datetime64[ns]', name=u'TTimeStamp', freq=None)

In [57]: i
Out[57]: DatetimeIndex(['2016-01-04 01:40:00', '2016-01-04 02:00:00', '2016-01-04 02:10:00', '2016-01-04 02:30:00', '2016-01-04 02:40:00'],
dtype='datetime64[ns]', name='TTimeStamp', freq=None)

In [58]: i.month
Out[58]: Int64Index([1, 1, 1, 1, 1], dtype='int64', name='TTimeStamp')

In [59]: i.month.isin([2,3])
Out[59]: array([False, False, False, False, False], dtype=bool)

In [60]: i.month.isin([1,2,3])
Out[60]: array([ True,  True,  True,  True,  True], dtype=bool)

更新2: 尝试以下解决方法:

compare[pd.Series(compare.index.get_level_values(0).month).isin([5, 6, 7]).values]

抱歉,我忘记补充说我也尝试过这个方法,但是没有成功...问题已经编辑,附带了我遇到的错误信息。 - victor
@victor,你能提供一个小的可复现的数据集吗? - MaxU - stand with Ukraine
我创建了DatetimeIndex并调用了i.month。但是,它没有创建Int54Index,而是创建了一个dtype为int32ndarray。看起来这就是错误的源头,调用month时创建了一个ndarray而不是Index对象。我检查了原始索引,同样的情况也发生了--包括month属性会导致DatetimeIndex被转换为ndarray。尽管如此,我还没有找到解决办法。 - victor
好的,那个完美地解决了!谢谢你提供的临时解决方法!不过我还是很好奇为什么要从DatetimeIndex对象创建ndarray--如果我弄清楚了,我会继续查找并在这里发布答案。 - victor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接