【问题标题】:Indexing timeseries by date string按日期字符串索引时间序列
【发布时间】:2012-11-24 03:36:07
【问题描述】:

给定一个时间序列s,它有一个日期时间索引,我希望能够按日期字符串对时间序列进行索引。我是否误解了这应该如何工作?

import pandas as pd
url = 'http://ichart.finance.yahoo.com/table.csvs=SPY&d=12&e=4&f=2012&g=d&a=01&b=01&c=2001&ignore=.csv'  
df = pd.read_csv(url, index_col='Date', parse_dates=True)  
s = df['Close']
s['2012-12-04']

结果:

TimeSeriesError                           Traceback (most recent call last)
<ipython-input-244-e2ccd4ecce94> in <module>()
      2 df = pd.read_csv(url, index_col='Date', parse_dates=True)  
      3 s = df['Close']  
----> 4 s['2012-12-04']

    G:\Python27-32\lib\site-packages\pandas\core\series.pyc in __getitem__(self, key)
    468     def __getitem__(self, key):
    469         try:
--> 470             return self.index.get_value(self, key)
    471         except InvalidIndexError:
    472             pass

    G:\Python27-32\lib\site-packages\pandas\tseries\index.pyc in get_value(self, series, key)  

   1030 
   1031             try:
-> 1032                 loc = self._get_string_slice(key)
   1033                 return series[loc]
   1034             except (TypeError, ValueError, KeyError):

G:\Python27-32\lib\site-packages\pandas\tseries\index.pyc in _get_string_slice(self, key)
   1077         asdt, parsed, reso = parse_time_string(key, freq)
   1078         key = asdt
-> 1079         loc = self._partial_date_slice(reso, parsed)
   1080         return loc
   1081 

G:\Python27-32\lib\site-packages\pandas\tseries\index.pyc in _partial_date_slice(self, reso, parsed)
    992     def _partial_date_slice(self, reso, parsed):
    993         if not self.is_monotonic:
--> 994             raise TimeSeriesError('Partial indexing only valid for ordered '
    995                                   'time series.')
    996 

TimeSeriesError: Partial indexing only valid for ordered time series. 

更具体地说(也许是迂腐的..),这里的 2 个 Timeseries 有什么区别:

import pandas as pd
url = 'http://ichart.finance.yahoo.com/table.csv?        s=SPY&d=12&e=4&f=2012&g=d&a=01&b=01&c=2001&ignore=.csv'
s = pd.read_csv(url, index_col='Date', parse_dates=True)['Close']
rng = date_range(start='2011-01-01', end='2011-12-31')
ts = Series(randn(len(rng)), index=rng)
print ts.__class__
print ts.index[0].__class__
print s1.__class__
print s1.index[0].__class__
print ts[ts.index[0]]
print s[s.index[0]]
print ts['2011-01-01']
try:
    print s['2012-12-05']
except:
    print "doesn't work" 

结果:

<class 'pandas.core.series.TimeSeries'>
<class 'pandas.lib.Timestamp'>
<class 'pandas.core.series.TimeSeries'>
<class 'pandas.lib.Timestamp'>
-0.608673793503
141.5
-0.608673793503
doesn't work

【问题讨论】:

  • 我在该网址上收到 404 错误。如果你复制一些表格会更容易,甚至更好的是df.to_dict()的输出。

标签: python pandas time-series


【解决方案1】:

尝试使用Timestamp 对象进行索引:

>>> import pandas as pd
>>> from pandas.lib import Timestamp
>>> url = 'http://ichart.finance.yahoo.com/table.csv?s=SPY&d=12&e=4&f=2012&g=d&a=01&b=01&c=2001&ignore=.csv'
>>> df = pd.read_csv(url, index_col='Date', parse_dates=True)
>>> s = df['Close']
>>> s[Timestamp('2012-12-04')]
141.25

【讨论】:

  • 是的,谢谢,我知道这会起作用。我的问题是为什么 s['2012-12-04'] 没有。这是一个错误,还是对于具有日期时间索引的时间序列应该如何工作?
  • @user1878647 它有一个时间戳索引而不是日期时间,尽管您也可以使用它的日期时间进行查找。您不能做的是使用未知日期格式的字符串进行查找(一方面,可能不清楚应该将其解释为哪个日期)。我会说这不是错误。
  • @hayden 上面示例中的 ts 和 s 都有时间戳索引,但行为不同。
【解决方案2】:

当时间序列未排序并且您提供部分时间戳(例如日期,而不是日期时间)时,不清楚应该选择哪个日期时间。

不能假设每个日期只有一个 datetime 对象,虽然在这个例子中有,这里有几个选项,但在这里抛出错误似乎比猜测用户的动机更安全。 (我们可以返回一个类似于.ix['2011-01'] 的系列/列表,但如果在其他情况下返回一个数字,这可能会令人困惑。我们可以尝试返回一个“最接近的匹配”......但这也没有任何意义。 )

在有序的情况下更容易,我们选择具有选定日期的第一个日期时间。

您可以在这个简单的示例中看到这种行为:

import pandas as pd
from numpy.random import randn
from random import shuffle
rng = pd.date_range(start='2011-01-01', end='2011-12-31')
rng2 = list(rng)
shuffle(rng2) # not in order
rng3 = list(rng)
del rng3[20] # in order, but no freq

ts = pd.Series(randn(len(rng)), index=rng)
ts2 = pd.Series(randn(len(rng)), index=rng2)
ts3 = pd.Series(randn(len(rng)-1), index=rng3)

ts.index
<class 'pandas.tseries.index.DatetimeIndex'>
[2011-01-01 00:00:00, ..., 2011-12-31 00:00:00]
Length: 365, Freq: D, Timezone: None

ts['2011-01-01']
# -1.1454418070543406

ts2.index
<class 'pandas.tseries.index.DatetimeIndex'>
[2011-04-16 00:00:00, ..., 2011-03-10 00:00:00]
Length: 365, Freq: None, Timezone: None

ts2['2011-01-01']
#...error which you describe
TimeSeriesError: Partial indexing only valid for ordered time series

ts3.index
<class 'pandas.tseries.index.DatetimeIndex'>
[2011-01-01 00:00:00, ..., 2011-12-31 00:00:00]
Length: 364, Freq: None, Timezone: None

ts3['2011-01-01']
1.7631554507355987


rng4 = pd.date_range(start='2011-01-01', end='2011-01-31', freq='H')
ts4 = pd.Series(randn(len(rng4)), index=rng4)

ts4['2011-01-01'] == ts4[0]
# True # it picks the first element with that date

我不认为这是一个错误,但我将其发布为an issue on github

【讨论】:

    【解决方案3】:

    虽然熊猫教程很有启发性,但我认为提出的原始问题值得直接回答。我在将 Yahoo 图表信息转换为可以切片的 DataFrame 等时遇到了同样的问题。我发现唯一需要的是:

    import pandas as pd
    import datetime as dt
    
    def dt_parser(date): 
    return dt.datetime.strptime(date, '%Y-%m-%d') + dt.timedelta(hours=16)
    
    url = 'http://ichart.finance.yahoo.com/table.csvs=SPY&d=12&e=4&f=2012&g=d&a=01&b=01&c=2001&ignore=.csv'  
    df = pd.read_csv(url, index_col=0, parse_dates=True, date_parser=dt_parser)
    df.sort_index(inplace=True)
    s = df['Close']
    s['2012-12-04']     # now should work
    

    “诀窍”是包含我自己的 date_parser。我猜在 read_csv 中有一些更好的方法可以做到这一点,但这至少产生了一个被索引并且可以被切片的 DataFrame。

    【讨论】:

      猜你喜欢
      • 2018-06-27
      • 1970-01-01
      • 2018-05-15
      • 1970-01-01
      • 2021-03-17
      • 1970-01-01
      • 2019-01-05
      • 2021-04-09
      • 2015-12-18
      相关资源
      最近更新 更多