展平 3D NumPy 数组中的内部元组并作为浮点数保存到 CSV
Posted
技术标签:
【中文标题】展平 3D NumPy 数组中的内部元组并作为浮点数保存到 CSV【英文标题】:Flatten inner tuples inside 3D NumPy array and save to CSV as floats 【发布时间】:2021-07-07 19:04:27 【问题描述】:当最里面的行包含混合类型的条目时,我想展平 3(/4) 维 NumPy 数组的最里面和最外面的轴:浮点数和浮点数的数组/元组。然后我想将其保存到一个 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=',')
【问题讨论】:
【参考方案1】:您的问题使用 3D 数组的示例,其中数组元素指针位于中心索引处,但是现有答案不会直接应用于您的示例输入/输出,而无需进一步的重要步骤。这是一个解决方案,它以高效简洁的方式实现了您所要求的(并将概括)从您的示例到 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 上包含内联代码/亮点。这通常位于键盘上 Esc
键的正下方。
【讨论】:
这正是我想要的。我希望我能用赏金奖励这个答案。非常感谢!【参考方案2】:此代码应该适用于问题中的特定场景。
-
访问最里面的数组
检查每个元素的实例
如果是
<class 'numpy.ndarray'>
类型,则调用.tolist()
将其转换为python 列表 并使用+
运算符将列表合并到现有的内部列表中
代码:
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]]]
【讨论】:
感谢您的回复。这有点复杂,您的 Axis 1 不在我的目标数组中。对于我在问题中提到的数百万行,“for”循环很慢。不过还是谢谢你,我已经了解了 .tolist 方法作为奖励。 @SO1999 是的,我同意这种方法可能会更慢。除此之外,输出与您在问题中提供的目标数组具有相同的结构。我没明白你说的那部分是什么意思。【参考方案3】:我认为可以公平地说,您的问题的核心是将 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 在其他地方得到了很好的介绍。
【讨论】:
感谢您的回复。这适用于整个数组的一个子数组的一行 - 使用两个“for”循环将其应用于每个子子数组是否会在大规模(例如 >1M 行)上有效? @SO1999,对不起,我不确定那个。如果您正在大规模地做类似的事情,并且您有多种外部循环的方法,那么可能值得尝试它们并使用“timeit”模块比较运行时。 我比较了 100 万行不同响应的时间,“for”循环比接受的答案慢得多。不过感谢您的回复,我已经了解了 .tolist 方法作为奖励【参考方案4】:当您显示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)
【讨论】:
以上是关于展平 3D NumPy 数组中的内部元组并作为浮点数保存到 CSV的主要内容,如果未能解决你的问题,请参考以下文章