如何有效地将熊猫数据帧重新采样到3d NumPy数组中?

时间:2020-06-17 21:31:23

标签: python pandas numpy python-xarray

我有一个带有DatetimeIndex和多列的大数据框。现在,我想有一个resample_3d操作,可以这样使用:

index, array = df.resample_3d("1h", fill_value=0)

...并转换数据框

index | A | B | C | D
10:00 | 1 |   | 
10:01 | 1 |   | 
12:00 | 1 |   |
13:00 | 1 |   |

转换为形状(3、2、4)的3d-NumPy数组。第一个维度是时间(可以在单独返回的index中查找),第二个维度是“重采样组”中的行索引,第三个维度是要素。第二维的大小等于单个重采样组中的最大行数。填充未使用的条目(例如用零填充)。

Pandas /另一个库中是否有这样的功能或类似的功能,还是有一种无需过多工作就可以在Pandas之上高效地实现类似功能的方法?

我知道我可以在df.resample().apply(list)之上构建一些东西,但是对于较大的数据帧来说,这太慢了。

我已经在Numba上开始了自己的实现,但随后很快意识到这是一项相当大的工作。

(我刚刚发现了xarray,并认为我用它来标记这个问题,因为它可能比Pandas更好。

1 个答案:

答案 0 :(得分:1)

不清楚您的数据是什么样的,但是,是的,xarray可能就是您要搜索的数据。

一旦您的数据格式正确为DataArray,您就可以这样做:

da.resample(time="1h")

它将返回一个DataArrayResample对象。

通常,在重新采样时,新的坐标网格与先前的网格不匹配。

因此,从那里开始,您需要应用众多methods of the DataArrayResample object中的一个来告诉xarray如何填充这个新网格。

例如,您可能希望使用原始数据作为节点来插值:

da.resample(time="1h").interpolate("linear")

但是您也可以回填,填充,使用最接近的值等。

如果您不想填充新的网格,请使用.asfreq(),新的时间将设置为NaN。以后您仍然可以使用interpolate_na()进行插值。

您的案子

在您的情况下,您似乎正在进行下采样,因此新的网格坐标和原始的网格坐标之间完全匹配。

因此,适用于您的方法是.nearest().asfreq().interpolate()(请注意,.interpolate()会将int转换为{{1 }}。

但是,由于您正以精确的网格结进行下采样,因此您真正要做的是选择数组的一个子集,因此您可能想使用.sel()方法。

示例

对精确的网格点结进行下采样的示例。

创建数据:

float

使用>>> dims = ("time", "features") >>> sizes = (6, 3) >>> h_step = 0.5 >>> da = xr.DataArray( dims=dims, data=np.arange(np.prod(sizes)).reshape(*sizes), coords=dict( time=pd.date_range( "04/07/2020", periods=sizes[0], freq=pd.DateOffset(hours=h_step), ), features=list(string.ascii_uppercase[: sizes[1]]), ), ) >>> da <xarray.DataArray (time: 6, features: 3)> array([[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8], [ 9, 10, 11], [12, 13, 14], [15, 16, 17]]) Coordinates: * time (time) datetime64[ns] 2020-04-07 ... 2020-04-07T02:30:00 * features (features) <U1 'A' 'B' 'C' >>> da.time.values array(['2020-04-07T00:00:00.000000000', '2020-04-07T00:30:00.000000000', '2020-04-07T01:00:00.000000000', '2020-04-07T01:30:00.000000000', '2020-04-07T02:00:00.000000000', '2020-04-07T02:30:00.000000000'], dtype='datetime64[ns]') .resample()下采样:

.nearest()

按选择下采样:

>>> da.resample(time="1h").nearest()
<xarray.DataArray (time: 3, features: 3)>
array([[ 0,  1,  2],
       [ 6,  7,  8],
       [12, 13, 14]])
Coordinates:
  * time      (time) datetime64[ns] 2020-04-07 ... 2020-04-07T02:00:00
  * features  (features) <U1 'A' 'B' 'C'

>>> da.resample(time="1h").nearest().time.values
array(['2020-04-07T00:00:00.000000000',
       '2020-04-07T01:00:00.000000000',
       '2020-04-07T02:00:00.000000000'],
      dtype='datetime64[ns]')

创建>>> dwn_step = 2 >>> new_time = pd.date_range( "04/07/2020", periods=sizes[0] // dwn_step, freq=pd.DateOffset(hours=h_step * dwn_step), ) >>> da.sel(time=new_time) <xarray.DataArray (time: 3, features: 3)> array([[ 0, 1, 2], [ 6, 7, 8], [12, 13, 14]]) Coordinates: * time (time) datetime64[ns] 2020-04-07 ... 2020-04-07T02:00:00 * features (features) <U1 'A' 'B' 'C' >>> da.sel(time=new_time).time.values array(['2020-04-07T00:00:00.000000000', '2020-04-07T01:00:00.000000000', '2020-04-07T02:00:00.000000000'], dtype='datetime64[ns]') 索引的另一种选择是:

new_time

它更直接,但是您不能选择第一个选定的时间(取决于您的情况,时间可以是好事或坏事)。