【问题标题】:Pandas DataFrame get rows where index matches a certain conditionPandas DataFrame 获取索引匹配特定条件的行
【发布时间】:2018-01-20 12:59:39
【问题描述】:

我有一个 Pandas 数据框,我需要索引匹配某个条件的所有行。数据框有一个 MultiIndex,我需要第一个索引 TimeStamp 在特定范围内的行。 MultiIndex 的第 1 级是一系列 DateTime 对象。以下代码行用于检查月份是否等于 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 版本是什么?
  • 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 语句中得到的输出。我正在使用熊猫 0.20.3
  • 请在我的回答中查看更新 - 我无法重现您的错误...我使用的是 Pandas 0.20.1

标签: python pandas dataframe


【解决方案1】:

试试这个:

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

PSthis should work for Pandas version 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)

UPDATE2:尝试以下解决方法:

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

【讨论】:

  • 对不起,我忘记补充了,我也试过了,但没用...问题被编辑了,我也遇到了错误
  • @victor,你能提供一个小的可重复数据集吗?
  • 我创建了DatetimeIndex 并调用了i.month。它不是创建一个Int54Index,而是创建一个dtype为int32的ndarray。这似乎是错误的根源,对month 的调用会创建ndarray 而不是Index 对象。我检查了原始索引,也发生了同样的事情——包括month 属性导致DatetimeIndex 被转换为ndarray。不过,我还没有找到解决方案。
  • 好的,效果很好!感谢您的解决方法!我仍然很好奇为什么 ndarray 是从 DatetimeIndex 对象创建的——如果我找出原因,我会继续四处寻找并在此处发布。
猜你喜欢
  • 2014-03-15
  • 1970-01-01
  • 2019-01-11
  • 2019-08-11
  • 2013-08-14
  • 2019-02-18
  • 2023-02-01
  • 2022-11-29
  • 1970-01-01
相关资源
最近更新 更多