基于数值与自定义类型的二维ndarray分组加权高效算法咨询
高效实现需求的解决方案
针对你提出的大规模数组处理需求,我们可以利用Pandas的向量化分组操作来实现高效计算——毕竟5000×3000的规模用循环逐行处理会慢到离谱,而Pandas的底层已经做了高度优化,能轻松应对这个量级的数据。
先明确核心逻辑(结合你的描述和示例,我优先贴合“按数值分10组后,统计每组内各类型的实际数量作为权重”的合理需求;如果你的真实需求是“每组直接分配该行类型总数的1/10”,我也会给出对应方案):
方案1:按分组内实际类型数量计算权重(符合数值分组的意义)
这个方案会严格按照每行数值从高到低分成10个分位数组,然后统计每个组内各类型的数量作为权重,完全匹配“按数值划分区域”的要求。
代码实现
import numpy as np import pandas as pd # 假设A和B是你已有的二维ndarray df_A = pd.DataFrame(A) df_B = pd.DataFrame(B) # 第一步:将宽表转长表,过滤掉NaN值(保留有数据的日期-区域对) stacked_values = df_A.stack(dropna=True).rename("feature_value") stacked_types = df_B.stack(dropna=True).rename("region_type") combined_df = pd.concat([stacked_values, stacked_types], axis=1).reset_index() combined_df.columns = ["date_idx", "region_idx", "value", "type"] # 第二步:对每个日期,按数值从高到低分成10组(组10=最高10%,组1=最低10%) # 处理特殊情况:如果某行有效数据不足10个,全部归为最高组(可根据需求调整) def split_into_10_groups(x): if len(x) < 10: return pd.Series([10]*len(x), index=x.index) return pd.qcut(x, q=10, labels=np.arange(10, 0, -1)) combined_df["group"] = combined_df.groupby("date_idx")["value"].apply(split_into_10_groups) # 第三步:统计每个日期-组-类型的权重(即该组内该类型的区域数量) group_weights = combined_df.groupby(["date_idx", "group", "type"]).size().unstack(fill_value=0) # 可选:补全所有30种类型(避免某些组缺失类型导致的列数不一致) all_types = combined_df["type"].unique() group_weights = group_weights.reindex(columns=all_types, fill_value=0)
结果说明
最终的group_weights是一个多级索引DataFrame:
- 行索引是
(日期索引, 组号)(比如(0,10)代表第0天的最高组) - 列是所有30种类型
- 单元格值就是该组该类型的权重(区域数量)
方案2:按每行类型总数的1/10分配权重(完全匹配你的示例)
如果你的需求确实是“不管分组内实际有多少该类型,每组直接分配该行该类型总数的1/10”(比如某行类型A有35个,每组A权重固定为3.5),那这个方案会更简单:
代码实现
# 基于上面的combined_df,先统计每个日期每个类型的总数 type_total_counts = combined_df.groupby(["date_idx", "type"]).size().unstack(fill_value=0) # 计算每个组的权重:总数除以10 per_group_base_weight = type_total_counts / 10 # 生成10组的索引,将每个日期的权重重复10次 group_labels = np.arange(10, 0, -1) multi_index = pd.MultiIndex.from_product([type_total_counts.index, group_labels], names=["date_idx", "group"]) # 生成最终的权重数组 final_weights = pd.DataFrame( np.repeat(per_group_base_weight.values, 10, axis=0), index=multi_index, columns=per_group_base_weight.columns )
效率说明
两种方案都避免了Python层面的循环,完全依赖Pandas/Numpy的C级向量化操作:
- 对于5000×3000的数组,即使有一半NaN,转长表后也只有750万行,Pandas处理这个量级的数据通常只需要几秒到十几秒。
- 如果你的内存足够(3000列的数组内存占用不大),可以放心运行。
内容的提问来源于stack exchange,提问作者sym44
相关产品推荐
相关产品推荐

