You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python工具计算3D矩阵各位置的时间占比超限值?

3D矩阵时间维度百分位数计算(向量化实现)

需求:针对(s,x,y)结构的3D数组(s为时间维度),计算每个(x,y)位置的时间序列中,被超过指定百分比的数值(即对应百分位数,例如指定90%时,结果为仅10%的时间点数值大于该值)。

示例数据构造

先基于你提供的示例创建xarray数据结构:

import xarray as xr
import numpy as np

# 构造时间维度s的5个切片
s1 = np.array([
    [4,44,71,98,22],
    [45,13,34,2,69],
    [95,82,7,62,83],
    [52,37,99,1,47],
    [13,11,64,52,29]
])
s2 = s1.copy()
s2[0,0] = 44
s3 = s1.copy()
s3[0,0] = 61
s4 = s1.copy()
s4[0,0] = 22
s5 = s1.copy()
s5[0,0] = 99

# 组合成3D数组并创建xarray DataArray
data = xr.DataArray(
    np.stack([s1, s2, s3, s4, s5]),
    dims=['s', 'x', 'y'],
    coords={'s': ['s1', 's2', 's3', 's4', 's5'],
            'x': range(5),
            'y': range(5)}
)

一、Xarray 方案(推荐,贴合你的现有工作流)

xarray原生支持按指定维度做统计聚合,quantile方法直接实现向量化计算,无需循环:

# 指定要计算的百分比:比如找被10%的数值超过的数(即90%分位数)
percentile = 0.9

# 按时间维度's'计算每个(x,y)的百分位数
result_xr = data.quantile(q=percentile, dim='s')

# 查看结果
print(result_xr.values)

解释:quantile(q=0.9, dim='s')会对每个(x,y)位置的时间序列(s维度的5个值)计算90%分位数,得到一个(5,5)的结果矩阵,每个值就是对应位置被10%时间点数值超过的阈值。


二、Pandas 方案

将xarray数据转换为MultiIndex DataFrame后,利用groupby或轴方向的quantile计算:

import pandas as pd

# 转换为MultiIndex DataFrame
df = data.to_dataframe(name='value').reset_index()

# 按x、y分组,计算每个组的百分位数
result_pd = df.groupby(['x', 'y'])['value'].quantile(q=percentile).unstack()

# 查看结果
print(result_pd.values)

解释:通过groupby(['x','y'])将每个(x,y)位置的时间序列分组,再对每组计算百分位数,最后unstack还原为二维矩阵结构。


三、Polars 方案(高性能,适合大数据场景)

Polars的向量化引擎性能优异,适合处理大规模数据:

import polars as pl

# 转换为Polars DataFrame
pl_df = pl.from_pandas(df)

# 按x、y分组计算百分位数
result_pl = pl_df.group_by(['x', 'y']).agg(
    pl.col('value').quantile(percentile)
).pivot(index='x', columns='y', values='value')

# 查看结果
print(result_pl.to_numpy())

解释:Polars的group_by+agg组合实现向量化分组统计,pivot操作将结果转换为二维矩阵,与需求结构匹配。


内容的提问来源于stack exchange,提问作者Always Learning

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 16:42:47