与Numpy不同,熊猫似乎并不喜欢记忆的进步

时间:2015-04-16 11:31:55

标签: python arrays pandas numpy dataframe

Pandas似乎缺少一个R风格的矩阵级滚动窗口函数(rollapply(..., by.column = FALSE)),只提供基于矢量的版本。因此,我尝试遵循this question并且它可以复制的示例非常有效,但即使使用(看似相同的)基础Numpy数组,它也不能与pandas DataFrame一起使用。

人工问题复制:

import numpy as np
import pandas as pd
from numpy.lib.stride_tricks import as_strided

test = [[x * y for x in range(1, 10)] for y in [10**z for z in range(5)]]
mm = np.array(test, dtype = np.int64)
pp = pd.DataFrame(test).values

mmpp看起来相同:

enter image description here

numpy直接派生矩阵给了我完美的想法:

as_strided(mm, (mm.shape[0] - 3 + 1, 3, mm.shape[1]), (mm.shape[1] * 8, mm.shape[1] * 8, 8))

也就是说,它在3d矩阵中给出了3个步幅,每个3行,允许我对一次向下移动一行的子矩阵执行计算。

enter image description here

但是pandas派生的版本(mm替换为pp的相同调用):

 as_strided(pp, (pp.shape[0] - 3 + 1, 3, pp.shape[1]), (pp.shape[1] * 8, pp.shape[1] * 8, 8))

enter image description here

就像它以某种方式转换一样奇怪。这与列/行主要订单有关吗?

我需要在Pandas中做矩阵滑动窗口,这似乎是我最好的镜头,特别是因为它真的很快。这里发生了什么?如何让底层的Pandas数组表现得像Numpy?

2 个答案:

答案 0 :(得分:12)

似乎.values以Fortran顺序返回基础数据(正如您推测的那样):

>>> mm.flags # NumPy array
  C_CONTIGUOUS : True
  F_CONTIGUOUS : False
  ...

>>> pp.flags # array from DataFrame
  C_CONTIGUOUS : False
  F_CONTIGUOUS : True
  ...

这使as_strided混淆,期望数据在内存中以C顺序排列。

要修复问题,您可以按C顺序复制数据并使用与问题相同的步幅:

pp = pp.copy('C') 

或者,如果您想避免复制大量数据,请调整步幅以确认数据的列顺序布局:

as_strided(pp, (pp.shape[0] - 3 + 1, 3, pp.shape[1]), (8, 8, pp.shape[0]*8))

答案 1 :(得分:4)

  

这与列/行主要订单有关吗?

是的,请参阅mm.stridespp.strides

  

如何让底层Pandas数组表现得像Numpy?

Numpy数组mm是“C-contiguous”,这就是为什么步幅技巧有效。如果要在DataFrame底层的数组上调用完全相同的代码,可以先使用np.ascontiguousarray。或者也许最好在考虑数组stridesitemsize的同时编写数据窗口。