展平 3D NumPy 数组中的内部元组并将其作为浮点数保存到 CSV

Flatten inner tuples inside 3D NumPy array and save to CSV as floats

当最里面的行包含混合类型的条目时,我想展平 3(/4) 维 NumPy 数组的最里面和最外面的轴:浮点数和 arrays/tuples 的浮点数。然后我想将其保存到一个 CSV 文件中,所有值都为 float64 类型。

have = [[[0.0 array([24.0,25.0]) 2.0 3.0]
         [4.0 array([26.0,27.0]) 6.0 7.0]
         [8.0 array([28.0,29.0]) 10.0 11.0]]

        [[12.0 array([30.0,31.0]) 14.0 15.0]
         [16.0 array([30.0,31.0]) 18.0 19.0]
         [20.0 array([30.0,31.0]) 22.0 23.0]]]

target = [[0.0 24.0 25.0 2.0 3.0]
              [4.0 26.0 27.0 6.0 7.0]
              [8.0 28.0 29.0 10.0 11.0]
              [12.0 30.0 31.0 14.0 15.0]
              [16.0 30.0 31.0 18.0 19.0]
              [20.0 30.0 31.0 22.0 23.0]]

np.savetxt('target.csv', target, delimiter=',')

当你显示 have 时,numpy 只知道它有一个 (2,4) 数组,其中一些条目是指向其他对象的指针(numpy 不知道那些是什么,但访问它们打印 have 时显示)。因此,任何解决方案都需要收集这些其他数组以将它们重新分配到别处,因为 numpy 不会提前知道所有数组的大小都相同。

import numpy as np

have         = np.array([[np.array([1,2]),5],[np.array([3,4]),7]])
target       = np.empty((2,3))      #Create some empty space
target[:,2]  = have[:,1]            #Reassign all the float points to their locations
target[:,:2] = np.vstack(have[:,0]) #Stack all the other arrays (assumes same size)

我认为可以公平地说,您的问题的核心是将 numpy.ndarrays 合并到现有的浮点数列表中,而不是对列表的外部维度进行操作。下面的代码段解决了这个问题,以您的第一个内部列表为例:

import numpy as np

iList = [0.0, np.array([24.0,25.0]), 2.0, 3.0]

newList = []
for i in iList:
    if type(i) == np.ndarray:
        lList = i.tolist()
        for l in lList:
            newList.append(l)
    else:
        newList.append(i)

如果您 运行 这个测试代码,您可以确认所有结果现在都是浮点数:

for x in newList:
    print(type(x))

输出:

<class 'float'>
<class 'float'>
<class 'float'>
<class 'float'>
<class 'float'>

保存为 CSV 在其他地方有详细介绍。

此代码应该适用于问题中的特定场景。

  1. 访问最里面的数组
  2. 检查每个元素的实例
  3. 如果它是 <class 'numpy.ndarray'> 类型调用 .tolist() 将其转换为 python list 并使用 + 运算符合并现有内部列表的列表

代码:

import numpy as np
have = [
    [
        [0.0, np.array([24.0,25.0]), 2.0, 3.0],
         [4.0, np.array([26.0,27.0]), 6.0, 7.0],
         [8.0, np.array([28.0,29.0]), 10.0, 11.0]
    ],

    [
        [12.0, np.array([30.0,31.0]), 14.0, 15.0],
         [16.0, np.array([30.0,31.0]), 18.0, 19.0],
         [20.0, np.array([30.0,31.0]), 22.0, 23.0]
    ]
]

tar = []
for i, e1 in enumerate(have):
    tar.append([])
    for j, e2 in enumerate(e1):
        temp = []
        for e3 in e2:
            if isinstance(e3, np.ndarray):
                temp += e3.tolist()
            else:
                temp.append(e3)
        tar[i].append(temp)

print(tar)

输出:

[[[0.0, 24.0, 25.0, 2.0, 3.0],
 [4.0, 26.0, 27.0, 6.0, 7.0],
 [8.0, 28.0, 29.0, 10.0, 11.0]],

[[12.0, 30.0, 31.0, 14.0, 15.0],
 [16.0, 30.0, 31.0, 18.0, 19.0], 
[20.0, 30.0, 31.0, 22.0, 23.0]]]

你的问题使用了一个 3D 数组的例子,在中心索引处有一个数组元素指针,但是现有的答案并不直接适用于你的例子 input/output 没有进一步的重要步骤。这是一个解决方案,它以高效简洁的方式实现了您要求(并将概括)从您的示例到 CSV 文件的所有内容。

首先让我们创建示例数组 have

>>> import numpy as np
>>> have = np.arange(24).reshape(2,3,4).astype('object')
>>> ins = np.arange(24,36)
>>> c = 0
>>> for i in range(2):
        for j in range(3):
            have[i][j][1] = np.array([ins[c], ins[c+1]])
            c += 2
>>> print(have)                                      # The exact array as in the question.
[[[0 array([24, 25]) 2 3]
  [4 array([26, 27]) 6 7]
  [8 array([28, 29]) 10 11]]

 [[12 array([30, 31]) 14 15]
  [16 array([32, 33]) 18 19]
  [20 array([34, 35]) 22 23]]]

现在我们将创建一个新数组成为您的 target 数组。

# Axis 1 is not needed as output will be all rows
#
all_rows          = np.vstack(have)
# Efficiently create dummy array of correct size
#                              
>>> target        = np.empty((have.shape[0]*have.shape[1], 4+1))
# LHS floats in correct positions
#
>>> target[:,:1]  = all_rows[:,:1]
# RHS floats in correct positions
#                             
>>> target[:,-2:] = all_rows[:,-2:]
# Slicing at a single index converts each array to floats
#
>>> target[:,1:3] = np.vstack(all_rows[:,1])    
>>> print(target)                                    # The exact array as in the question.
[[ 0. 24. 25.  2.  3.]
 [ 4. 26. 27.  6.  7.]
 [ 8. 28. 29. 10. 11.]
 [12. 30. 31. 14. 15.]
 [16. 32. 33. 18. 19.]
 [20. 34. 35. 22. 23.]]

这会生成一个数组 target,其中包含所有 float64 类型的条目,因此我们可以完全按照您在问题中的建议保存到当前目录中的 CSV 文件。

>>> np.savetxt('target.csv', target, delimiter=',')

另外让您知道,您可以在 Stack Overflow 中包含内联 code/highlights,使用单个 'backticks' 而不是问题中使用的普通单引号。这通常位于键盘上 Esc 键的正下方。