0

我在 Pandas 中遇到时间戳选择问题。

对于我所看到的,这是其他人遇到的问题(选择由 DatetimeIndex 索引的 Pandas DataFrame 的子集和 TimeStamps 列表),但不幸的是,Pandas 的开发人员拒绝接受它作为错误(https://github. com/pydata/pandas/issues/2437)。

在任何情况下,我都无法按照我上面引用的 SO 帖子提出的解决方法,因为我的数据不是以 CSV 文件的形式出现,而是在许多列表中(实际上我是从互联网通过 JSON 获取并转换那要列出)。

我得到的数据是这样的:

the_dataTransactions
[{u'date': u'1365100630', u'tid': 240264, u'price': u'132.58', u'amount': u'1.28309000'}, {u'date': u'1365100630', u'tid': 240263, u'price': u'132.58', u'amount': u'1.20294000'}, {u'date': u'1365100629', u'tid': 240262, u'price': u'132.58', u'amount': u'0.90893940'}]

我将其转换为:

transactionsDate
[datetime.datetime(2013, 4, 4, 19, 37, 10), datetime.datetime(2013, 4, 4, 19, 37, 10), datetime.datetime(2013, 4, 4, 19, 37, 9)]

我也试过这个,但是当我尝试选择一个数据范围时,结果中的错误是一样的:

transactionsDate
[<Timestamp: 2013-04-04 19:37:10>, <Timestamp: 2013-04-04 19:37:10>, <Timestamp: 2013-04-04 19:37:09>]

tid、price 和 amount 也添加到数据框中,例如:

>>> transactionsDF.info()
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 73 entries, 2013-04-04 19:37:10 to 2013-04-04 19:22:49
Data columns:
tid       73  non-null values
price     73  non-null values
amount    73  non-null values
dtypes: float64(2), int64(1)

>>> transactionsDF.head()
                        tid   price    amount
2013-04-04 19:37:10  240264  132.58  1.283090
2013-04-04 19:37:10  240264  132.58  1.283090
2013-04-04 19:37:10  240263  132.58  1.202940
2013-04-04 19:37:09  240262  132.58  0.908939
2013-04-04 19:37:09  240261  132.59  0.213051

但是,当我尝试使用正常表示法选择数据范围时,我得到了与另一篇文章中报告的相同的错误:

>>> transactionsDF['2013-04-03 18:00:00':'2013-04-04 19:00:00']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pandas/core/frame.py", line 1951, in __getitem__
    indexer = self.ix._convert_to_indexer(key, axis=0)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pandas/core/indexing.py", line 478, in _convert_to_indexer
    i, j = labels.slice_locs(start, stop)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pandas/tseries/index.py", line 1153, in slice_locs
    start_loc = self._get_string_slice(start).start
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pandas/tseries/index.py", line 1143, in _get_string_slice
    loc = self._partial_date_slice(reso, parsed)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pandas/tseries/index.py", line 1041, in _partial_date_slice
    raise TimeSeriesError('Partial indexing only valid for ordered '
pandas.tseries.index.TimeSeriesError: Partial indexing only valid for ordered time series.

我的数据似乎是有序的时间序列。你能考虑在这种特殊情况下解决这个 Pandas 故障吗?

更新(已解决?): 我找到了一种非常简单的方法,以至于我不完全确定它每次都会给出正确的答案,但至少对于一个小数据框来说它是有效的。代码只是:

transactionsDF = transactionsDF.sort_index()

在这之后似乎工作正常,并允许我选择一个数据范围,就像我过去使用其他数据一样:transactionsDF['2013-04-04 19:30':'2013-04-04 19:35']

也许更有知识的人可能会验证或取消验证此解决方法。

4

1 回答 1

1

我认为没有真正优雅的解决方案。Pandas 不喜欢重复索引。(至少是我拥有的稍微旧的版本。)您可以创建具有重复索引的 DataFrame,但您无法轻松访问它们的内容。

因此,您应该将日期放在单独的列中。然后,您可以使用日期上的比较运算符和精美的索引来访问有趣的行:

In [1]: import pandas as pd

In [5]: import datetime

In [15]: f1 = pd.DataFrame([{u'date': u'1365100630', u'tid': 240264, u'price': u'132.58', u'amount': u'1.28309000'}, {u'date': u'1365100630', u'tid': 240263, u'price': u'132.58', u'amount': u'1.20294000'}, {u'date': u'1365100629', u'tid': 240262, u'price': u'132.58', u'amount': u'0.90893940'}])

In [16]: f1["dates"] = [datetime.datetime(2013, 4, 4, 19, 37, 10), datetime.datetime(2013, 4, 4, 19, 37, 10), datetime.datetime(2013, 4, 4, 19, 37, 9)]

In [17]: f1
Out[17]: 
       amount        date   price     tid                dates
0  1.28309000  1365100630  132.58  240264  2013-04-04 19:37:10
1  1.20294000  1365100630  132.58  240263  2013-04-04 19:37:10
2  0.90893940  1365100629  132.58  240262  2013-04-04 19:37:09

In [25]: matching = (f1["dates"] >= datetime.datetime(2013, 4, 4, 19, 37, 10)) & (f1["dates"] < datetime.datetime(2013, 4, 4, 20, 00, 00))

In [26]: f1.ix[matching]
Out[26]: 
       amount        date   price     tid                dates
0  1.28309000  1365100630  132.58  240264  2013-04-04 19:37:10
1  1.20294000  1365100630  132.58  240263  2013-04-04 19:37:10

您也可以使用f1[matching]来访问有趣的行,但我觉得不太清楚,因为f1["foo"]用于访问列。

于 2013-04-04T20:11:09.337 回答