Pandas: преобразование временных рядов значений для отслеживания изменений в значении

#python #pandas #time-series

#python #pandas #временные ряды

Вопрос:

Я был в тупике по этому поводу, и — что нехарактерно — Интернет мало помог. Я работаю в Pandas, но я чувствую, что это должно быть общей проблемой для людей, стремящихся эффективно хранить данные временных рядов.

У меня много стандартных данных ежедневных временных рядов, где значения меняются нечасто, например:

Date Value
01/02/2014 .1
01/03/2014 .1
01/04/2014 .5
01/05/2014 .5
01/06/2014 .5
01/07/2014 .1

Я бы преобразовал данные только для отслеживания дней, когда изменяется значение, поэтому приведенный выше пример теперь должен выглядеть так:

Date Value
01/02/2014 .1
01/04/2014 .5
01/07/2014 .1

К сожалению, использование чего-то подобного drop_duplicates() приведет к удалению требуемых значений в случае, когда значение возвращается к предыдущему значению (например .1 в моем примере выше).

Ответ №1:

Используйте комбинацию shift и all :

 In [98]:

import io
temp = """Date,Value
01/02/2014,.1
01/03/2014,.1
01/04/2014,.5
01/05/2014,.5
01/06/2014,.5
01/07/2014,.1"""
df = pd.read_csv(io.StringIO(temp))
df
Out[98]:
         Date  Value
0  01/02/2014    0.1
1  01/03/2014    0.1
2  01/04/2014    0.5
3  01/05/2014    0.5
4  01/06/2014    0.5
5  01/07/2014    0.1

In [99]:

df.loc[(df.shift() != df).all(axis=1)]
Out[99]:
         Date  Value
0  01/02/2014    0.1
2  01/04/2014    0.5
5  01/07/2014    0.1
 

Здесь мы сравниваем сдвинутый (на 1 строку) фрейм данных с исходным фреймом данных, затем мы хотим сравнить каждый столбец и использовать all и передавать axis=1 для достижения этой цели.

Дальнейшая разбивка, если мы посмотрим, что df.shift() != df возвращает:

 In [100]:

df.shift() != df
Out[100]:
   Date  Value
0  True   True
1  True  False
2  True   True
3  True  False
4  True  False
5  True   True
 

Мы получаем фрейм данных с логическими значениями, но мы не можем использовать это как маску как есть, мы хотим проверить, что все строки таковы True , что мы используем all :

 In [101]:

(df.shift() != df).all()
Out[101]:
Date      True
Value    False
dtype: bool
 

Однако по умолчанию проверяется, что столбцы все True , мы хотим проверить значения строк, поэтому мы передаем axis=1 :

 In [102]:

(df.shift() != df).all(axis=1)
Out[102]:
0     True
1    False
2     True
3    False
4    False
5     True
dtype: bool
 

Теперь мы можем использовать это как нашу логическую маску для достижения того, чего мы хотели:

 In [103]:

df.loc[(df.shift() != df).all(axis=1)]
Out[103]:
         Date  Value
0  01/02/2014    0.1
2  01/04/2014    0.5
5  01/07/2014    0.1
 

Комментарии:

1. хм … хотя мы добавили это в кулинарную книгу (и, возможно, где-то в основных документах). хотите это сделать? полный пример этого

2. @Джефф рад, это просто ссылка на этот ответ?

3. Я думаю, что небольшой полный пример был бы хорош (я считаю, что встроенный код лучше для небольшого примера)

4. @Jeff нужно ли мне загружать исходный код и компилировать его: pandas.pydata.org / … не уверен, что у меня возникнут проблемы, поскольку я использую WinPython, который поставляется с python

5. @Jeff спасибо за ссылку, я попробую и посмотрю, как у меня дела, я хотел бы внести больший вклад, а не просто мои основные ответы на SO