基于行列提取大型NumPy数组子集的Pythonic实现方法问询
问题背景
我有一个1,125,000行、150列的大型NumPy数组,需要提取特定子集:保留所有列,但每列要先重塑成(50,150,150)的三维数组,再取出其中[:, 56:67, 56:67]的部分(对应50×11×11=6050个元素)。想找个高效的Pythonic实现,下面是我针对3列数组写的循环示例代码:
import numpy as np import pandas as pd data_1 = np.random.random((50,150, 150)) data_2 = np.random.random((50,150, 150)) data_3 = np.random.random((50,150, 150)) big_array = np.concatenate((data_1, data_2, data_3), axis=1).reshape(1125000, 3) df= pd.DataFrame() for i in range(big_array.shape[1]): df_1 = big_array[:,i] print(df_1.shape) df_1 = df_1.reshape(50, 150, 150) df_1 = df_1[:, 56:67, 56:67].reshape(-1) print(df_1.shape) df_2 = pd.DataFrame(df_1) df_2[i] = df_2 print(df_2.shape) #df = pd.concat([df_2[i]], axis=1) df = df.append(df_2[i]) print(i) df.T
高效实现方案
别用循环逐列处理了,直接用NumPy的向量化操作,速度快得多,代码也更简洁:
import numpy as np import pandas as pd # 假设big_array是你的(1125000, 150)大型数组 # 1. 转置数组,把原数组的每一列变成新数组的一行,再整体重塑为四维数组 reshaped = big_array.T.reshape(-1, 50, 150, 150) # 2. 批量提取每个三维数组的目标区域,然后展平每一列的结果 extracted = reshaped[:, :, 56:67, 56:67].reshape(150, -1) # 3. 转置后转成DataFrame,和你原来循环得到的df.T结果完全一致 result_df = pd.DataFrame(extracted.T)
为什么这么做?
- 速度碾压循环:Python循环处理百万级数据效率极低,NumPy的底层是C实现的批量操作,能把速度提升几个数量级,150列的话差距尤其明显。
- 避免DataFrame的低效操作:你原来用
append逐列拼DataFrame,每次append都会创建新对象,数据量大的时候慢到离谱。先全用NumPy处理完再转成DataFrame,一步到位。 - 形状变换逻辑拆解:
big_array.T把数组转成(150, 1125000),每一行对应原数组的一列;.reshape(-1, 50, 150, 150)自动把每一行拆成(50,150,150)的三维数组,最终得到(150,50,150,150)的四维数组;- 切片
[:, :, 56:67, 56:67]一次性提取所有列的目标区域; .reshape(150, -1)把每个列的目标区域展平成一维,最后转置就得到和原代码一样的(6050,150)结构。
内容的提问来源于stack exchange,提问作者bluered_earth
相关产品推荐
相关产品推荐

