在Pandas中找到最接近给定时间的DataFrame行

17

我有一个以DatetimeIndex为索引的Pandas数据框:

<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 53732 entries, 1993-01-07 12:23:58 to 2012-12-02 20:06:23
Data columns:
Date(dd-mm-yy)_Time(hh-mm-ss)       53732  non-null values
Julian_Day                          53732  non-null values
AOT_870                             53732  non-null values
440-870Angstrom                     53732  non-null values
440-675Angstrom                     53732  non-null values
500-870Angstrom                     53732  non-null values
Last_Processing_Date(dd/mm/yyyy)    53732  non-null values
Solar_Zenith_Angle                  53732  non-null values
time                                53732  non-null values
dtypes: datetime64[ns](2), float64(6), object(1)

我希望找到最接近特定时间的行:
image_time = dateutil.parser.parse('2009-07-28 13:39:02')

我会翻译中文。以下是需要翻译的内容:

并找出它有多接近。到目前为止,我尝试了各种基于减去我想要的时间并找到最小绝对值的想法,但似乎都不太行。

例如:

aeronet.index - image_time

出现了一个错误,我认为是由于日期时间索引上的+/-导致的偏移,因此我尝试将索引放入另一列中,然后在该列上进行操作:

aeronet['time'] = aeronet.index
aeronet.time - image_time

这似乎可行,但为了达到我的目的,我需要获取绝对时间差,而不是相对差异。但是,仅运行absnp.abs会导致错误:
abs(aeronet.time - image_time)

C:\Python27\lib\site-packages\pandas\core\series.pyc in __repr__(self)
   1061         Yields Bytestring in Py2, Unicode String in py3.
   1062         """
-> 1063         return str(self)
   1064 
   1065     def _tidy_repr(self, max_vals=20):

C:\Python27\lib\site-packages\pandas\core\series.pyc in __str__(self)
   1021         if py3compat.PY3:
   1022             return self.__unicode__()
-> 1023         return self.__bytes__()
   1024 
   1025     def __bytes__(self):

C:\Python27\lib\site-packages\pandas\core\series.pyc in __bytes__(self)
   1031         """
   1032         encoding = com.get_option("display.encoding")
-> 1033         return self.__unicode__().encode(encoding, 'replace')
   1034 
   1035     def __unicode__(self):

C:\Python27\lib\site-packages\pandas\core\series.pyc in __unicode__(self)
   1044                     else get_option("display.max_rows"))
   1045         if len(self.index) > (max_rows or 1000):
-> 1046             result = self._tidy_repr(min(30, max_rows - 4))
   1047         elif len(self.index) > 0:
   1048             result = self._get_repr(print_header=True,

C:\Python27\lib\site-packages\pandas\core\series.pyc in _tidy_repr(self, max_vals)
   1069         """
   1070         num = max_vals // 2
-> 1071         head = self[:num]._get_repr(print_header=True, length=False,
   1072                                     name=False)
   1073         tail = self[-(max_vals - num):]._get_repr(print_header=False,

AttributeError: 'numpy.ndarray' object has no attribute '_get_repr'

我这样做是正确的吗?如果是,我该如何让abs工作,以便我可以选择最小的绝对时间差,从而得到最接近的时间。如果不是,那么使用Pandas时间序列的最佳方法是什么?

3个回答

20
这种简单方法可以返回最接近给定日期时间对象的TimeSeriesIndex条目(整数索引)。无需将索引复制到普通列 - 只需使用.to_pydatetime方法即可。
import numpy as np

i = np.argmin(np.abs(df.index.to_pydatetime() - image_time))

然后你只需使用 DataFrame 的 .iloc 索引器:

df.iloc[i]

这里有一个实现此功能的函数:

def fcl(df, dtObj):
    return df.iloc[np.argmin(np.abs(df.index.to_pydatetime() - dtObj))]

您可以轻松地进一步无缝过滤信息,例如:

fcl(df, dtObj)['column']

似乎应该有更简单的方法,但这是一个不错的解决方案,帮助我继续前进! - mishaF

8
我认为你可以尝试使用 DatetimeIndex.asof 来查找最近的标签(包括输入),然后使用返回的日期时间来选择相应的行。如果您只需要特定列的值,则存在 Series.asof,它将上述两个步骤合并为一个步骤。
这假设您想要最接近的日期时间。如果你不关心日期,只是想每天在同一时间,那么在 DataFrame 中使用 at_time
跟进:

编辑:虚惊一场,我本地有一个较旧的版本。主库中的最新版本应该能使用 np.abs。

In [10]: np.abs(df.time - image_time)
Out[10]: 
0    27 days, 13:39:02
1    26 days, 13:39:02
2    25 days, 13:39:02
3    24 days, 13:39:02
4    23 days, 13:39:02
5    22 days, 13:39:02

仅作澄清:

aeronet.index - image_time的计算无效,因为在索引上进行减法等价于集合差(早些时候,索引被限制为唯一)。


1
谢谢 - 这很有帮助。然而,我不认为它会一直做我想要的事情。例如,如果我在10:25、10:32有数据,并使用10:30调用asof,它将返回10:25,而不是实际更接近的10:32。也就是说,我想要的是最接近的时间,而不一定是给定时间之前最接近的时间。也许我需要使用我的手动方法来完成,但我看不出为什么np.abs不能工作。 - robintw
感谢您的跟进。我今天早些时候(大约UTC下午3点)从http://pandas.pydata.org/pandas-build/dev/安装了最新的开发版本 - 自那时以来是否已更改以允许np.abs? (我将在明天上班时测试最新的开发版本) - robintw
我不这么认为。另外看一下错误,问题不在计算中,而是在结果的输出上。如果你将结果分配给一个变量,你可能能够查找并找出问题所在。 - Chang She
我尝试将其分配给一个变量,但结果完全相同。这似乎相当奇怪。我应该向pandas团队报告一个错误吗? - robintw
请在 GitHub 上提出问题。在提问时,能否提供更清晰的细节,例如,您能否将数据集缩小到一个小的规模,并提供一个自包含的可重现示例?这将有助于我们调试问题。谢谢。 - Chang She

5

今天我遇到了同样的问题。我想要一个能够给我指定时间戳之前最接近的值的函数。以下是我得到的函数:

def get_nearest_past(data, timestamp):
    index = data.index.get_loc(timestamp,"ffill")
    return data.iloc[index]

如果您需要全局最近(而不是像我这样的之前最近),可以使用以下方法:

def get_nearest(data, timestamp):
    index = data.index.get_loc(timestamp,"nearest")
    return data.iloc[index]

您可以在get_loc文档中找到更多信息。


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