Найдите ближайшую строку DataFrame до заданного времени в Pandas
У меня есть Pandas dataframe, который индексируется DatetimeIndex:
<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
Дает ошибку, которая, как мне кажется, связана с +/- в индексе Datetime, меняющим вещи, поэтому я попытался помещать индекс в другой столбец, а затем работал над этим:
aeronet['time'] = aeronet.index
aeronet.time - image_time
Кажется, что это работает, но для того, чтобы делать то, что я хочу, мне нужно получить разницу по времени ABSOLUTE, а не относительную разницу. Однако при запуске abs
или np.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?
Ответы
Ответ 1
Я думаю, вы можете попробовать DatetimeIndex.asof
найти самую последнюю метку вплоть до ввода и включить ее. Затем используйте возвращенное время datetime для выбора соответствующей строки.
Если вам нужны только значения для определенного столбца, Series.asof
существует и объединяет два шага выше в один.
Это предполагает, что вы хотите получить самое близкое время и время. Если вам не нужна дата и просто нужно одно и то же время каждый день, используйте at_time
в DataFrame.
Последующие действия:
Изменить: ложный сигнал тревоги, у меня была более ранняя версия локально. Последний из мастеров должен работать с 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 не работает, потому что вычитание по индексу является заданной разницей (в тот же день, когда индекс был ограничен, чтобы быть уникальным).
Ответ 2
Этот простой метод вернет индекс (целочисленный индекс) элемента TimeSeriesIndex, ближайший к данному объекту datetime. Нет необходимости копировать индекс в обычный столбец - просто используйте метод .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']