Панды раздвижные окна - PullRequest
0 голосов
/ 24 июня 2018

У меня есть следующие импортированные панды DataFrame, проиндексированные по дате и времени:

                             VAL
           DATETIME    
2012-01-02 02:00:00    3.375000
2012-01-02 02:01:00    3.281667
2012-01-02 02:02:00    3.426667
2012-01-02 02:03:00    3.378333
2012-01-02 02:04:00    3.381667
2012-01-02 02:05:00    3.831667
....

Мне нужно преобразовать DataFrame следующим образом:

                            VAL        VAL1        VAL2
           DATETIME    
2012-01-02 02:00:00    3.375000    3.281667    3.426667
2012-01-02 02:01:00    3.281667    3.426667    3.378333
2012-01-02 02:02:00    3.426667    3.378333    3.381667
2012-01-02 02:03:00    3.378333    3.381667    3.831667
...

Если есть встроенная функцияили эффективный способ достижения этого?

Ответы [ 2 ]

0 голосов
/ 24 июня 2018

Вы можете использовать NumPy stride_tricks:

import numpy as np
import numpy.lib.stride_tricks as stride
import pandas as pd
df = pd.DataFrame({'DATETIME': ['2012-01-02 02:00:00', '2012-01-02 02:01:00', '2012-01-02 02:02:00', '2012-01-02 02:03:00', '2012-01-02 02:04:00', '2012-01-02 02:05:00'], 'VAL': [3.375, 3.2816669999999997, 3.4266669999999997, 3.378333, 3.3816669999999998, 3.831667]})
df['DATETIME']  = pd.to_datetime(df['DATETIME'])
df = df.set_index('DATETIME')


stride = df['VAL'].values.strides[0]
ncols = 3
nrows = len(df)-ncols+1
arr = stride.as_strided(df['VAL'], shape=(nrows, ncols), strides=(stride, stride))

result = pd.DataFrame(arr.copy(), columns=['VAL{}'.format(i) for i in range(1, ncols+1)],
                      index=df.index[:nrows])

выходы

                         VAL1      VAL2      VAL3
DATETIME                                         
2012-01-02 02:00:00  3.375000  3.281667  3.426667
2012-01-02 02:01:00  3.281667  3.426667  3.378333
2012-01-02 02:02:00  3.426667  3.378333  3.381667
2012-01-02 02:03:00  3.378333  3.381667  3.831667

strides=(stride,stride) - ключ к изготовлению раздвижных окон. Оно говорит stride.as_strided что в каждом месте в result следующее значение право (т. е. в следующем столбце) составляет stride байтов и каждое значение вниз (то есть в следующем ряду) также только на stride байтов. Байты, определяющие значения в result взяты из базового массива, arr.copy().


Хотя stride_tricks может очень быстро создать нужный массив, Есть предостережения, связанные с его использованием. См. Ниже и Примечания на странице документа . Эти предостережения полностью смягчаются путем копирования массива - то есть с использованием arr.copy() вместо arr. С другой стороны, копирование массива, особенно большого размера, снижает производительность.


Обратите внимание, что если вы используете pd.DataFrame(arr) вместо pd.DataFrame(arr.copy()), тогда значения в DataFrame имеют вид из df['VAL']. Хотя это эффективно для памяти, это также означает, что изменение одного значения в result может изменить значение в нескольких местах. Например,

result = pd.DataFrame(arr, columns=['VAL{}'.format(i) for i in range(1, ncols+1)],
                      index=df.index[:nrows])

In [30]: result.iloc[1,1] = 100
In [27]: result
Out[27]: 
                           VAL1        VAL2        VAL3
DATETIME                                               
2012-01-02 02:00:00    3.375000    3.281667  100.000000
2012-01-02 02:01:00    3.281667  100.000000    3.378333
2012-01-02 02:02:00  100.000000    3.378333    3.381667
2012-01-02 02:03:00    3.378333    3.381667    3.831667

Если вы хотите, чтобы каждое значение было независимым, используйте arr.copy().

0 голосов
/ 24 июня 2018

Используйте Series.shift с циклом для назначения нескольких новых столбцов:

for x in range(1, 3):
    df['VAL{}'.format(x)] = df['VAL'].shift(-x)

При необходимости сдвиг на одну минуту:

for x in range(1, 3):
    df['VAL{}'.format(x)] = df['VAL'].shift(-x, freq='T')

print (df)
                          VAL      VAL1      VAL2
DATETIME                                         
2012-01-02 02:00:00  3.375000  3.281667  3.426667
2012-01-02 02:01:00  3.281667  3.426667  3.378333
2012-01-02 02:02:00  3.426667  3.378333  3.381667
2012-01-02 02:03:00  3.378333  3.381667  3.831667
2012-01-02 02:04:00  3.381667  3.831667       NaN
2012-01-02 02:05:00  3.831667       NaN       NaN

Последний, если необходимо, удалите последние строки с помощью NaN s:

#N > 1
N = 3
for x in range(1, N):
    df['VAL{}'.format(x)] = df['VAL'].shift(-x, freq='T')

df = df.iloc[:-N + 1]
print (df)
                          VAL      VAL1      VAL2
DATETIME                                         
2012-01-02 02:00:00  3.375000  3.281667  3.426667
2012-01-02 02:01:00  3.281667  3.426667  3.378333
2012-01-02 02:02:00  3.426667  3.378333  3.381667
2012-01-02 02:03:00  3.378333  3.381667  3.831667
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...