python - 如何有效地将 Pandas 数据帧重新采样为 3d NumPy 数组?
问题描述
我有一个包含一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 更好的基础。)
解决方案
目前尚不清楚您的数据是什么样的,但是是的,xarray 可能是您搜索的内容。
一旦您的数据格式DataArray
正确,您就可以执行以下操作:
da.resample(time="1h")
它将返回一个DataArrayResample
对象。
通常,重采样时,新的坐标网格与之前的网格不匹配。
因此,从那里,您需要应用对象的众多方法之一DataArrayResample
来告诉 xarray 如何填充这个新网格。
例如,您可能希望使用原始数据作为节点来插值:
da.resample(time="1h").interpolate("linear")
但您也可以回填、填充、使用最接近的值等。
如果您不想填充新网格,则使用.asfreq()
和新时间将设置为 NaN。您仍然可以稍后使用interpolate_na()
.
你的情况
在您的情况下,您似乎正在进行下采样,因此新网格坐标和原始网格坐标之间存在完全匹配。
因此,适用于您的方法是.nearest()
, .asfreq()
,中的任何一个.interpolate()
(请注意,.interpolate()
将转换int
为float
)。
但是,由于您是在精确的网格节点处进行下采样,因此您真正要做的是选择数组的一个子集,因此您可能希望改用该.sel()
方法。
例子
对精确网格点节点进行下采样的示例。
创建数据:
>>> 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
索引的另一种选择是仅执行以下操作:
new_time = da.time[::dwn_coeff]
它更直接,但您不能选择第一个选择的时间(根据您的情况,这可能是好是坏)。
推荐阅读
- mongodb - 带有 upsert=true 的 Mongodb UpdateMany。有什么方法可以识别修改的记录吗?
- java - 如何使用 exoplayer 检测视频是否包含声音
- postman - 在 Postman 中定义多个变量和初始值
- git - 没有什么可以比较的
- java - 从 gradle 中以管理员身份运行 groovy 脚本,即没有管理员命令提示符
- flutter - How do i use flutter variables from main.dart in other screen.dart files in the same lib folder?
- vue.js - 如何在 vue 测试工具中模拟 navigator.clipboard.writeText
- angular6 - 如何在 Angular 8 中使用 web api 创建动态图表
- asp.net-core - 即使对于完全限定的引用,省略 using 语句也会导致错误
- database - AS 函数在 LARAVEL 数据库语句中不起作用