【问题标题】:Pandas: Unstack a sliding window?Pandas:取消堆叠滑动窗口?
【发布时间】:2021-07-02 22:05:45
【问题描述】:

我有一个 110 万行的数据框,需要以以下滚动方式处理:

假设窗口大小为 2

         A    B
0   "This"    3
1     "is"    4
2      "a"    5
3   "test"    6

输出将是:

      A_1     A_2  B_1  B_2
0  "This"    "is"    3    4
1    "is"     "a"    4    5
2     "a"  "test"    5    6

我目前正在通过遍历数据框来执行此操作,但处理如此大的数据集需要 3 个小时。

有没有更有效的方法来做到这一点?

【问题讨论】:

  • 真实数据只有2列?
  • 不,真实数据可能有更多列
  • 如果窗口为 3,预期的输出是什么?

标签: python pandas rolling-computation sliding-window


【解决方案1】:

一个想法,大步前进并分别广播每一列,因为不同的类型:

def rolling_window(a, window):
    shape = a.shape[:-1] + (a.shape[-1] - window + 1, window)
    strides = a.strides + (a.strides[-1],)
    return np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides)

N = 2
a = rolling_window(np.arange(len(df)), N)
print (a)
[[0 1]
 [1 2]
 [2 3]]

df = pd.concat([pd.DataFrame(df[x].to_numpy()[a]).rename(columns=lambda y: f'{x}_{y + 1}')
                for x in df.columns], axis=1)
print (df)
    A_1   A_2  B_1  B_2
0  This    is    3    4
1    is     a    4    5
2     a  test    5    6

如果需要3

N = 3
a = rolling_window(np.arange(len(df)), N)
print (a)
[[0 1 2]
 [1 2 3]]

df = pd.concat([pd.DataFrame(df[x].to_numpy()[a]).rename(columns=lambda y: f'{x}_{y + 1}')
                for x in df.columns], axis=1)
print (df)
    A_1 A_2   A_3  B_1  B_2  B_3
0  This  is     a    3    4    5
1    is   a  test    4    5    6

numpy 解决方案的性能很好:

#8 columns, 400krows
df = pd.concat([df] * 4, ignore_index=True, axis=1)
df.columns = list('ABCDEFGH')
df = pd.concat([df] * 100000, ignore_index=True)


In [53]: %%timeit
    ...: a = rolling_window(np.arange(len(df)), 2)
    ...: pd.concat([pd.DataFrame(df[x].to_numpy()[a]).rename(columns=lambda y: f'{x}_{y + 1}') for x in df.columns], axis=1)
    ...: 
    ...: 
167 ms ± 741 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [54]: %%timeit
    ...: window = 2
    ...: pd.DataFrame({ f'{col}_{i}': list(df[col][i-1:len(df)-window+i]) for col in df.columns for i in range(1,window+1) })
    ...: 
    ...: 
1.52 s ± 2.61 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

【讨论】:

  • 点了。我怀疑我写的内容可以优化,但可能不是 10 倍...... :)
  • 一个很好的解决方案,性能很好,正是我需要的!谢谢
【解决方案2】:

Java支持匿名数组的特性,所以在传递数组给方法时不需要声明数组。

代码

//@GIOCHE

公共类 TestAnonymousArray{

/创建一个接收方法
数组作为参数
/

static void printArray(int arr[])

{

for(int i = 0; i

System.Out.Println(arr[i]);

}

public static void main(String args[]) {

//将匿名数组传递给方法

printArray(new int[] {10,22,44,66});

输出 10 22 44 66

【讨论】:

  • 我认为您在错误的页面上发布了答案...
猜你喜欢
  • 2018-01-08
  • 2023-01-11
  • 1970-01-01
  • 2021-06-22
  • 1970-01-01
  • 2015-02-21
  • 1970-01-01
  • 2018-12-17
  • 2019-10-04
相关资源
最近更新 更多