Вы можете использовать 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()
.