2D到3D块numpy数组

hl0ma9xz  于 2023-08-05  发布在  其他
关注(0)|答案(3)|浏览(113)

我有以下二维 Dataframe conc,对应于一系列波长wl下4层上的气体浓度:

conc =  
        wl    gas1  gas2  gas3  layer
    0   5000  10    13    250    1
    1   5000  20    14    260    2
    2   5000  30    15    270    3
    3   5000  40    16    280    4
    4   5001  50    17    290    1
    5   5001  60    18    300    2
    6   5001  70    19    310    3
    7   5001  80    20    320    4
    ...
    497 5125  20    25    650    1
    498 5125  35    15    550    2
    499 5125  55    30    750    3
    500 5125  95    21    650    4

字符串
我想通过沿着第三维放置4线块(4层1波长)将其转换为3D阵列。
我使用循环来完成它,但由于我的数组非常大,它需要很长时间。有没有一种方法可以不使用循环?

wls = set(conc.loc[:,"wl"])
new_3D_array = np.zeros((len(wls), 4, 3))   # 4 layers, 3 gases

for k, wl in enumerate(wls):
    sub_array = conc[conc.loc[:,"wl"]==wl]
    new_3D_array[k,:,:] = sub_array.loc[:,["gas1", "gas2", "gas3"]]


所需输出为

[[[ 10.  13. 250.]
  [ 20.  14. 260.]
  [ 30.  15. 270.]
  [ 40.  16. 280.]]

 [[ 50.  17. 290.]
  [ 60.  18. 300.]
  [ 70.  19. 310.]
  [ 80.  20. 320.]]

 ....

 [[ 20.  25. 650.]
  [ 35.  15. 550.]
  [ 55.  30. 750.]
  [ 95.  21. 650.]]]

lkaoscv7

lkaoscv71#

您可以重塑:

size = conc[['wl', 'layer']].nunique()

out = (conc
  .set_index(['wl', 'layer'])
  .unstack('layer').stack('layer', dropna=False)
  .to_numpy().reshape((size['wl'], size['layer'], -1))
)

字符串

  • 注意。stack/unstack步骤仅在您没有wl/layer和顺序的所有组合时才需要。*

输出量:

array([[[ 10,  13, 250],
        [ 20,  14, 260],
        [ 30,  15, 270],
        [ 40,  16, 280]],

       [[ 50,  17, 290],
        [ 60,  18, 300],
        [ 70,  19, 310],
        [ 80,  20, 320]],

       [[ 20,  25, 650],
        [ 35,  15, 550],
        [ 55,  30, 750],
        [ 95,  21, 650]]])

lvmkulzt

lvmkulzt2#

如果你想用一个循环来做,你可以得到每个波长的每个2DTensor,然后把它们连接起来:

tensor_3D = []
for w in conc["w1"].unique():
    tensor_2D = conc[conc["w1"]==w].drop("w1", axis=1)
    tensor_3D.append(tensor_2D.to_numpy())

tensor_3D = np.array(tensor_3D)

字符串
编辑:我觉得你可能总是要为此做一个循环,你也可以用一种更优雅的方式来做:

conc_grouped = conc.groupby("w1")
tensor_3D = np.array([conc_grouped.get_group(c).to_numpy() for c in conc_grouped.groups.keys()])

w8rqjzmb

w8rqjzmb3#

这是xarray的工作:

np.moveaxis(conc.set_index(['wl','layer']).to_xarray().to_array().to_numpy(),0,-1)

字符串
xarray是一种基于标记多索引的多维数据。它有自己的API和逻辑(xarray是python的另一个多索引数据表示包。这里我只是使用pandas的能力来转换为xarray)。
因此,to_array()将其转换为数组(可使用整数索引)。你不能df.to_xarray()[0,0,0],而df.to_xarray().to_array()[0,0,0]是一个合法的请求。但即使这样,它仍然是一个“xarray的数组”。[0,0,0]返回一个xarray项。因此,看似多余的to_numpy()将其转换为正确的numpy数组(其值只是浮点数)。因此,即使这3个转换(pandas dataframe到xarray dataframe; xarray Dataframe 到xarray数组; xarray数组到numpy数组)似乎是多余的,它们都是需要的。但最后两个人实际上什么也没做;它们不移动或复制数据。
我需要最后的moveaxis,因为否则,“剩余的列”(因此gas 1,gas 2,gas 3:不用作索引的列)轴是第一个。因此,要获得第100个波长的第4层的“gas 2”,您需要使用[1,99,3]索引,而您希望的输出应该使用[99,3,1]索引。但同样,移动轴也不需要任何成本(不需要数据复制或移动)。只是一些调整的步伐)。
时机明智,这是不可分辨的,从mozway的答案为一个例子,同样大小的你。在我的机器上,两者都是5.6毫秒(基于for的解决方案是10.1毫秒)。
当n增长时,在两个向量化解决方案中的哪一个更快变得清楚之前,需要相当多的数据。在1000行之后,差别就很明显了,例如,对于100000行,这个解决方案需要260 ms,而mozway的解决方案需要505 ms。它似乎渐进地达到了这个~2的时序比(相对于具有100000行的基于for的解决方案的820秒)。通常,向量化的解决方案比非向量化的解决方案好1000倍。因此,相比之下,两个矢量化解决方案之间的因子2似乎并不多)。
请注意,即使你不需要任何导入(除了你已经拥有的pandas)来运行这一行,它也依赖于包xarray,而xarray并不总是安装有pandas(因此,在一个安装了pandas但没有xarray的系统上,pandas方法to_xarray存在,但只是引发一个错误)。换句话说,您可能需要pip install xarray

相关问题