为什么我需要更改访问Pandas中使用DatetimeIndex索引的数据帧的频率



我在Stackoverflow的这篇文章中找到了这个例子:

import pandas as pd
earliest = pd.Timestamp('2012-01-01 06:00:00')
latest = pd.Timestamp('2014-12-01 23:00:00')
dr = pd.date_range(start=earliest, end=latest,freq="30min")
df_freq = pd.DataFrame(index=dr, columns=['freq'])
df_freq = df_freq.fillna(0)
# use str datetime as key 
df_freq['2012-03-04']

这篇文章发表在大约五年前,所以API熊猫可能已经改变了。即使代码在2022年仍然有效,我也收到了以下警告:

FutureWarning: Indexing a DataFrame with a datetimelike index using a single string
to slice the rows, like `frame[string]`, is deprecated and will be removed in a future 
version. Use `frame.loc[string]` instead.

然而,这种按日期时间进行的索引似乎只适用于特定的频率。如果您将频率从"30min"更改为"D"(每天(,则相同的片段不起作用:

import pandas as pd
earliest = pd.Timestamp('2012-01-01')
latest = pd.Timestamp('2014-12-01')
dr = pd.date_range(start=earliest, end=latest, freq="D")     # if freq is D, it does not work
df_freq = pd.DataFrame(index=dr, columns=['freq'])
df_freq = df_freq.fillna(0)
df_freq['2012-03-04']

在这种情况下,我得到了一条KeyError: '2012-03-04'错误消息。

解决方法很简单,必须使用df_freq.loc['2012-03-04']进行索引。然而,我不知道为什么我需要更改访问数据帧的频率。这种行为在其他地方有记录吗?

当前pandas docs表示:

警告

使用带有getitem的单个字符串索引DataFrame行(例如。frame[dtstring](不赞成从pandas 1.2.0开始使用(给定模糊性,无论是对行进行索引还是选择列(以及将在将来的版本中删除。.loc的等效项(例如。frame.loc[dtstring](。

当您查看版本1.1.5(即1.2.0之前的最后一个版本(的文档时,您会发现您的问题已经包含在其中:

警告

但是,如果字符串被视为完全匹配,则中的选择DataFrame的[]将按列而非按行,请参阅索引基础知识。例如dft_minute['2011-12-31 23:59']将引发KeyError由于"2012-12-31 23:59"具有与索引相同的分辨率没有这样名称的列:

为了始终具有明确的选择,无论行是否被视为切片或单个选择,使用.loc.

因此,回到您的具体情况,在使用freq="30min"的第一个示例中,df_freq['2012-03-04']而不是完全匹配。例如:

print(df_freq['2012-03-04'].head())
freq
2012-03-04 00:00:00     0
2012-03-04 00:30:00     0
2012-03-04 01:00:00     0
2012-03-04 01:30:00     0
2012-03-04 02:00:00     0

但是,在使用freq="D"的第二个示例中,df_freq['2012-03-04']确实构成了完全匹配。结果,程序开始寻找column匹配,而不是index匹配。由于您的df_freq没有任何这样的列,因此您会收到错误。事实上,应用于第二个示例的df_freq['2012-03-04']回溯的最后一部分向您展示了以下内容:

Traceback (most recent call last):
File "script.py", line 8, in <module>
df_freq['2012-03-04']
File "..pandascoreframe.py", line 3505, in __getitem__
indexer = self.columns.get_loc(key)
File "..pandascoreindexesbase.py", line 3623, in get_loc
raise KeyError(key) from err
KeyError: '2012-03-04'

indexer = self.columns.get_loc(key)。即故障在于df_freq.columns.get_loc('2012-03-04')

所以,这个问题实际上与所选频率无关。第二个例子中的df_freq['2012-03']仍然会给你一个切片(当然,也有同样的警告(。

使用CCD_ 19也可以避免该问题。应用于您的第二个示例:

print(df_freq['2012-03-04':'2012-03-04'])
freq
2012-03-04     0

但是,请注意,这将返回一个df切片:

print(type(df_freq['2012-03-04':'2012-03-04']))
<class 'pandas.core.frame.DataFrame'>

对比度.loc:

print(type(df_freq.loc['2012-03-04']))
<class 'pandas.core.series.Series'>

相关内容

最新更新