Pau*_*ers 7 python numpy pandas
假设我有以下代码:
import numpy as np
import pandas as pd
x = np.array([1.0, 1.1, 1.2, 1.3, 1.4])
s = pd.Series(x, index=[1, 2, 3, 4, 5])
Run Code Online (Sandbox Code Playgroud)
这产生以下结果s:
1 1.0
2 1.1
3 1.2
4 1.3
5 1.4
Run Code Online (Sandbox Code Playgroud)
现在我想要创建的是一个大小的滚动窗口n,但我不想采用每个窗口的均值或标准偏差,我只想要数组.所以,假设n = 3.我想要一个转换,根据输入输出以下系列s:
1 array([1.0, nan, nan])
2 array([1.1, 1.0, nan])
3 array([1.2, 1.1, 1.0])
4 array([1.3, 1.2, 1.1])
5 array([1.4, 1.3, 1.2])
Run Code Online (Sandbox Code Playgroud)
我该怎么做呢?
Zer*_*ero 12
这是一种方法
In [294]: arr = [s.shift(x).values[::-1][:3] for x in range(len(s))[::-1]]
In [295]: arr
Out[295]:
[array([ 1., nan, nan]),
array([ 1.1, 1. , nan]),
array([ 1.2, 1.1, 1. ]),
array([ 1.3, 1.2, 1.1]),
array([ 1.4, 1.3, 1.2])]
In [296]: pd.Series(arr, index=s.index)
Out[296]:
1 [1.0, nan, nan]
2 [1.1, 1.0, nan]
3 [1.2, 1.1, 1.0]
4 [1.3, 1.2, 1.1]
5 [1.4, 1.3, 1.2]
dtype: object
Run Code Online (Sandbox Code Playgroud)
这是使用NumPy broadcasting- 的矢量化方法
n = 3 # window length
idx = np.arange(n)[::-1] + np.arange(len(s))[:,None] - n + 1
out = s.get_values()[idx]
out[idx<0] = np.nan
Run Code Online (Sandbox Code Playgroud)
这样可以将输出作为2D数组。
要获得将每个窗口作为列表的每个元素的序列,请执行以下操作:
In [40]: pd.Series(out.tolist())
Out[40]:
0 [1.0, nan, nan]
1 [1.1, 1.0, nan]
2 [1.2, 1.1, 1.0]
3 [1.3, 1.2, 1.1]
4 [1.4, 1.3, 1.2]
dtype: object
Run Code Online (Sandbox Code Playgroud)
如果希望拥有一维数组拆分数组的列表,则可以np.split在输出中使用,如下所示:
out_split = np.split(out,out.shape[0],axis=0)
Run Code Online (Sandbox Code Playgroud)
样品运行-
In [100]: s
Out[100]:
1 1.0
2 1.1
3 1.2
4 1.3
5 1.4
dtype: float64
In [101]: n = 3
In [102]: idx = np.arange(n)[::-1] + np.arange(len(s))[:,None] - n + 1
...: out = s.get_values()[idx]
...: out[idx<0] = np.nan
...:
In [103]: out
Out[103]:
array([[ 1. , nan, nan],
[ 1.1, 1. , nan],
[ 1.2, 1.1, 1. ],
[ 1.3, 1.2, 1.1],
[ 1.4, 1.3, 1.2]])
In [104]: np.split(out,out.shape[0],axis=0)
Out[104]:
[array([[ 1., nan, nan]]),
array([[ 1.1, 1. , nan]]),
array([[ 1.2, 1.1, 1. ]]),
array([[ 1.3, 1.2, 1.1]]),
array([[ 1.4, 1.3, 1.2]])]
Run Code Online (Sandbox Code Playgroud)
strides为了提高内存效率,我们可以使用跨步的- strided_axis0,类似于@B. M.'s solution,但更通用一些。
因此,要获得第一个元素为NaN的2D值数组-
In [35]: strided_axis0(s.values, fillval=np.nan, L=3)
Out[35]:
array([[nan, nan, 1. ],
[nan, 1. , 1.1],
[1. , 1.1, 1.2],
[1.1, 1.2, 1.3],
[1.2, 1.3, 1.4]])
Run Code Online (Sandbox Code Playgroud)
如问题中所述,要获得以NaNs为填充值的2D数组,紧随每一行中的原始元素以及元素被翻转的顺序,如下所示:
In [36]: strided_axis0(s.values, fillval=np.nan, L=3)[:,::-1]
Out[36]:
array([[1. , nan, nan],
[1.1, 1. , nan],
[1.2, 1.1, 1. ],
[1.3, 1.2, 1.1],
[1.4, 1.3, 1.2]])
Run Code Online (Sandbox Code Playgroud)
为了得到与每个元件保持每个窗口作为一个列表,只需用包裹早期方法的一系列pd.Series(out.tolist())与out作为2D阵列输出-
In [38]: pd.Series(strided_axis0(s.values, fillval=np.nan, L=3)[:,::-1].tolist())
Out[38]:
0 [1.0, nan, nan]
1 [1.1, 1.0, nan]
2 [1.2, 1.1, 1.0]
3 [1.3, 1.2, 1.1]
4 [1.4, 1.3, 1.2]
dtype: object
Run Code Online (Sandbox Code Playgroud)