使用多个形状 2 的数组填充形状 3 的数组

Populating an array of shape 3 with multiple arrays of shape 2

提问人:Caesar 提问时间:10/28/2023 更新时间:10/28/2023 访问量:56

问:

我需要一些帮助来更好地表达这个问题的标题。

但我本质上有一个由 2d 数组组成的 dataframe(即每行都是一个名为 ab[y][x] 的 2d 图片,其中 x,y 是整数)。我正在尝试使用数据帧中的每个 2d 数组创建一个具有形状的数组。 也可以认为是每个二维数组中的行数,也可以认为是每个二维数组中的列数。我将在下面包括一个 MRE:(number of rows in data frame, len(x), len(y))len(x)len(y)

import numpy as np 
import pandas as pd

data = {"ab[0][0]": [329, 392, 9294, 4922, 9324, 95839],
        "ab[0][1]": [23, 27, 3299, 827, 60, 47],
        "ab[0][2]": [80, 32, 50, 782, 934, 93],
        "ab[0][3]": [90, 100, 53, 438, 50, 53], 
        "ab[1][0]": [6000, 245, 24, 204, 2390, 7248],
        "ab[1][1]": [23, 5324, 13, 45, 60, 435],
        "ab[1][2]": [4253, 53, 5035, 75, 82, 8347],
        "ab[1][3]": [843, 9403, 70, 434, 50, 828],
        "ab[2][0]": [600, 5000, 10342, 3453, 3553, 9834],
        "ab[2][1]": [23, 27, 13, 45, 8493, 70],
        "ab[2][2]": [4983, 4872, 28, 75, 60, 843],
        "ab[2][3]": [48739, 2389, 3478, 827, 932, 83], 
}

ab_df = pd.DataFrame(data)
ab_values = []

for i in range(ab_df.shape[0]):
  individual_ab = []
  for j in range(3): # can think of 3 as the x-values on an x-y graph (or 3 columns)
    ab_columns = [col for col in ab_df.columns if f'ab[{j}]' in col]
    individual_ab.append(ab_df.iloc[[i]][ab_columns].T.values)
    
  if len (individual_ab) > 0: # so I don't add an empty list to the end of the array
    ab_values.append(np.hstack(individual_ab))
      
ab_arr = np.stack(ab_values) # should have (6, 4, 3)

我的解决方案实际上使用了三个 for 循环,并且在处理具有 1000+ 行的数据帧时速度非常慢。

我的主要问题是,有没有更好的方法来做到这一点,也许是通过使用一些 numpy 或 pandas 函数或更好的算法?

我的附带问题是,对于我的 x 轴的长度(即),有没有办法使用数据自动计算出这一点,现在我正在手动编码 3,如上面的示例所示,但是说进来的数据发生了变化,我想要一种方法来自动更改该值。我一直在试图找出解决这个问题的方法,但我就是无法解决它。for j in range(3)

python 数组 pandas 算法 numpy

评论

0赞 Paul H 10/28/2023
我很好奇你是如何得出这种输入数据格式的。我怀疑最好的解决方案是这个数据管道的上游

答:

1赞 Timeless 10/28/2023 #1

IIUC,可以直接对 DataFrame 进行整形

N = 3 # or maybe N = ab_df.shape[0] // 2 ?

ab_arr = np.reshape(ab_df, (-1, ab_df.shape[1]//N, N), order="F")

输出:

array([[[  329,  6000,   600],
        [   23,    23,    23],
        [   80,  4253,  4983],
        [   90,   843, 48739]],

       [[  392,   245,  5000],
        [   27,  5324,    27],
        [   32,    53,  4872],
        [  100,  9403,  2389]],

       [[ 9294,    24, 10342],
        [ 3299,    13,    13],
        [   50,  5035,    28],
        [   53,    70,  3478]],

       [[ 4922,   204,  3453],
        [  827,    45,    45],
        [  782,    75,    75],
        [  438,   434,   827]],

       [[ 9324,  2390,  3553],
        [   60,    60,  8493],
        [  934,    82,    60],
        [   50,    50,   932]],

       [[95839,  7248,  9834],
        [   47,   435,    70],
        [   93,  8347,   843],
        [   53,   828,    83]]])
1赞 hpaulj 10/28/2023 #2

有了那个:data

In [108]: data
Out[108]: 
{'ab[0][0]': [329, 392, 9294, 4922, 9324, 95839],
 'ab[0][1]': [23, 27, 3299, 827, 60, 47],
 'ab[0][2]': [80, 32, 50, 782, 934, 93],
 'ab[0][3]': [90, 100, 53, 438, 50, 53],
 'ab[1][0]': [6000, 245, 24, 204, 2390, 7248],
 'ab[1][1]': [23, 5324, 13, 45, 60, 435],
 'ab[1][2]': [4253, 53, 5035, 75, 82, 8347],
 'ab[1][3]': [843, 9403, 70, 434, 50, 828],
 'ab[2][0]': [600, 5000, 10342, 3453, 3553, 9834],
 'ab[2][1]': [23, 27, 13, 45, 8493, 70],
 'ab[2][2]': [4983, 4872, 28, 75, 60, 843],
 'ab[2][3]': [48739, 2389, 3478, 827, 932, 83]}

框架是:

In [109]: ab_df
Out[109]: 
   ab[0][0]  ab[0][1]  ab[0][2]  ab[0][3]  ab[1][0]  ab[1][1]  ab[1][2]  \
0       329        23        80        90      6000        23      4253   
1       392        27        32       100       245      5324        53   
2      9294      3299        50        53        24        13      5035   
3      4922       827       782       438       204        45        75   
4      9324        60       934        50      2390        60        82   
5     95839        47        93        53      7248       435      8347   

   ab[1][3]  ab[2][0]  ab[2][1]  ab[2][2]  ab[2][3]  
0       843       600        23      4983     48739  
1      9403      5000        27      4872      2389  
2        70     10342        13        28      3478  
3       434      3453        45        75       827  
4        50      3553      8493        60       932  
5       828      9834        70       843        83  

从中你可以很容易地得到一个数组,每行一行,每行一列:

In [111]: arr = ab_df.to_numpy()

In [112]: arr
Out[112]: 
array([[  329,    23,    80,    90,  6000,    23,  4253,   843,   600,
           23,  4983, 48739],
       [  392,    27,    32,   100,   245,  5324,    53,  9403,  5000,
           27,  4872,  2389],
       [ 9294,  3299,    50,    53,    24,    13,  5035,    70, 10342,
           13,    28,  3478],
       [ 4922,   827,   782,   438,   204,    45,    75,   434,  3453,
           45,    75,   827],
       [ 9324,    60,   934,    50,  2390,    60,    82,    50,  3553,
         8493,    60,   932],
       [95839,    47,    93,    53,  7248,   435,  8347,   828,  9834,
           70,   843,    83]], dtype=int64)

In [113]: arr.shape
Out[113]: (6, 12)

重塑这样的数组,或转置它,等等都很容易。

In [116]: arr.reshape(3,4,-1)
Out[116]: 
array([[[  329,    23,    80,    90,  6000,    23],
        [ 4253,   843,   600,    23,  4983, 48739],
        [  392,    27,    32,   100,   245,  5324],
        [   53,  9403,  5000,    27,  4872,  2389]],

       [[ 9294,  3299,    50,    53,    24,    13],
        [ 5035,    70, 10342,    13,    28,  3478],
        [ 4922,   827,   782,   438,   204,    45],
        [   75,   434,  3453,    45,    75,   827]],

       [[ 9324,    60,   934,    50,  2390,    60],
        [   82,    50,  3553,  8493,    60,   932],
        [95839,    47,    93,    53,  7248,   435],
        [ 8347,   828,  9834,    70,   843,    83]]], dtype=int64)

或者也许你想要

In [120]: arr.T.reshape(3,4,6)
Out[120]: 
array([[[  329,   392,  9294,  4922,  9324, 95839],
        [   23,    27,  3299,   827,    60,    47],
        [   80,    32,    50,   782,   934,    93],
        [   90,   100,    53,   438,    50,    53]],

       [[ 6000,   245,    24,   204,  2390,  7248],
        [   23,  5324,    13,    45,    60,   435],
        [ 4253,    53,  5035,    75,    82,  8347],
        [  843,  9403,    70,   434,    50,   828]],

       [[  600,  5000, 10342,  3453,  3553,  9834],
        [   23,    27,    13,    45,  8493,    70],
        [ 4983,  4872,    28,    75,    60,   843],
        [48739,  2389,  3478,   827,   932,    83]]], dtype=int64)