使用 Python 创建 3D 数组
Posted
技术标签:
【中文标题】使用 Python 创建 3D 数组【英文标题】:Create 3D array using Python 【发布时间】:2012-05-26 22:55:47 【问题描述】:我想在 Python (2.7) 中创建一个 3D 数组,以便像这样使用:
distance[i][j][k]
数组的大小应该是我拥有的变量的大小。 (nnn)
我尝试使用:
distance = [[[]*n]*n]
但这似乎不起作用。
我只能使用默认库,而乘法(即[[0]*n]*n
)不起作用,因为它们链接到同一个指针,我需要所有值都是单独的
【问题讨论】:
考虑使用标准array
模块的array
类。
【参考方案1】:
正确的方法是
[[[0 for _ in range(n)] for _ in range(n)] for _ in range(n)]
(你想要做的应该写成(for NxNxN)
[[[0]*n]*n]*n
但这不正确,请参阅@Adaman 评论原因)。
【讨论】:
不好。它将包含对同一数组的引用。试试这个:a = [[0] * 3] * 3; a[0][0] = 1; print a
【参考方案2】:
numpy.array
s 专为这种情况而设计:
numpy.zeros((i,j,k))
会给你一个维度为 ijk 的数组,用零填充。
根据您的需要,numpy 可能是满足您需求的正确库。
【讨论】:
哦,我还以为这是默认库之一。我不能使用除此之外的任何东西。 不,不幸的是它是一个外部库。但如果您需要处理(大)数字数据数组,通常非常适合。特别是如果速度是一个问题。 我定义了一个这样的数组:new_array= numpy.zeros((6340,200,200)) 但它占用了 1.9GB 的内存空间。正常吗? @gocen 是的,听起来不错。 numpy zeroes 返回的默认值是 numpy.float64 和 6340*200*200*64bits = 2.0288 GB。您可以提供一个额外的参数dtype
为零来更改它返回的类型并以这种方式节省一些 RAM。【参考方案3】:
如果您坚持将所有内容初始化为空,则需要在内部使用一组额外的括号([[]] 而不是 [],因为这是“包含 1 个要复制的空列表的列表”而不是“一个不包含任何重复内容的列表”):
distance=[[[[]]*n]*n]*n
【讨论】:
不要那样做,否则它们都会指向同一个引用!试试distance[1][2][0].append(1)
是的,我的问题是如果我改变其中一个,它也会改变所有的。我需要它们是独立的元素。【参考方案4】:
你应该使用list comprehension:
>>> import pprint
>>> n = 3
>>> distance = [[[0 for k in xrange(n)] for j in xrange(n)] for i in xrange(n)]
>>> pprint.pprint(distance)
[[[0, 0, 0], [0, 0, 0], [0, 0, 0]],
[[0, 0, 0], [0, 0, 0], [0, 0, 0]],
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]]
>>> distance[0][1]
[0, 0, 0]
>>> distance[0][1][2]
0
您可以生成一个数据结构,其中包含一个看起来像您尝试过的语句的语句,但它会产生副作用,因为内部列表是按引用复制的:
>>> distance=[[[0]*n]*n]*n
>>> pprint.pprint(distance)
[[[0, 0, 0], [0, 0, 0], [0, 0, 0]],
[[0, 0, 0], [0, 0, 0], [0, 0, 0]],
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]]
>>> distance[0][0][0] = 1
>>> pprint.pprint(distance)
[[[1, 0, 0], [1, 0, 0], [1, 0, 0]],
[[1, 0, 0], [1, 0, 0], [1, 0, 0]],
[[1, 0, 0], [1, 0, 0], [1, 0, 0]]]
【讨论】:
对于 Python3,您可以将 xrange 更改为 range。 我使用了'copy-by-reference'方法,却不知道后端实际发生了什么。因此,我最终得到了“副作用”(我的变量中的所有字段最终都具有相同的值)并且不知道为什么。谢谢你的解释。【参考方案5】:d3 = [[[0 for col in range(4)]for row in range(4)] for x in range(6)]
d3[1][2][1] = 144
d3[4][3][0] = 3.12
for x in range(len(d3)):
print d3[x]
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 144, 0, 0], [0, 0, 0, 0]]
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [3.12, 0, 0, 0]]
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
【讨论】:
【参考方案6】:def n_arr(n, default=0, size=1):
if n is 0:
return default
return [n_arr(n-1, default, size) for _ in range(size)]
arr = n_arr(3, 42, 3)
assert arr[2][2][2], 42
【讨论】:
【参考方案7】:"""
Create 3D array for given dimensions - (x, y, z)
@author: Naimish Agarwal
"""
def three_d_array(value, *dim):
"""
Create 3D-array
:param dim: a tuple of dimensions - (x, y, z)
:param value: value with which 3D-array is to be filled
:return: 3D-array
"""
return [[[value for _ in xrange(dim[2])] for _ in xrange(dim[1])] for _ in xrange(dim[0])]
if __name__ == "__main__":
array = three_d_array(False, *(2, 3, 1))
x = len(array)
y = len(array[0])
z = len(array[0][0])
print x, y, z
array[0][0][0] = True
array[1][1][0] = True
print array
对于多维数组,首选使用numpy.ndarray
。
【讨论】:
【参考方案8】:您还可以使用嵌套的for
循环,如下所示
n = 3
arr = []
for x in range(n):
arr.append([])
for y in range(n):
arr[x].append([])
for z in range(n):
arr[x][y].append(0)
print(arr)
【讨论】:
【参考方案9】:有很多方法可以解决您的问题。
-
@robert 接受的第一个答案。这里是广义的
解决方案:
def multi_dimensional_list(value, *args):
#args dimensions as many you like. EG: [*args = 4,3,2 => x=4, y=3, z=2]
#value can only be of immutable type. So, don't pass a list here. Acceptable value = 0, -1, 'X', etc.
if len(args) > 1:
return [ multi_dimensional_list(value, *args[1:]) for col in range(args[0])]
elif len(args) == 1: #base case of recursion
return [ value for col in range(args[0])]
else: #edge case when no values of dimensions is specified.
return None
例如:
>>> multi_dimensional_list(-1, 3, 4) #2D list
[[-1, -1, -1, -1], [-1, -1, -1, -1], [-1, -1, -1, -1]]
>>> multi_dimensional_list(-1, 4, 3, 2) #3D list
[[[-1, -1], [-1, -1], [-1, -1]], [[-1, -1], [-1, -1], [-1, -1]], [[-1, -1], [-1, -1], [-1, -1]], [[-1, -1], [-1, -1], [-1, -1]]]
>>> multi_dimensional_list(-1, 2, 3, 2, 2 ) #4D list
[[[[-1, -1], [-1, -1]], [[-1, -1], [-1, -1]], [[-1, -1], [-1, -1]]], [[[-1, -1], [-1, -1]], [[-1, -1], [-1, -1]], [[-1, -1], [-1, -1]]]]
P.S 如果您热衷于验证 args 的正确值,即只有自然数,那么您可以在调用此函数之前编写一个包装函数。
-
其次,任何多维数组都可以写成一维数组。这意味着您不需要多维数组。下面是索引转换的函数:
def convert_single_to_multi(value, max_dim):
dim_count = len(max_dim)
values = [0]*dim_count
for i in range(dim_count-1, -1, -1): #reverse iteration
values[i] = value%max_dim[i]
value /= max_dim[i]
return values
def convert_multi_to_single(values, max_dim):
dim_count = len(max_dim)
value = 0
length_of_dimension = 1
for i in range(dim_count-1, -1, -1): #reverse iteration
value += values[i]*length_of_dimension
length_of_dimension *= max_dim[i]
return value
因为这些函数是互逆的,所以输出如下:
>>> convert_single_to_multi(convert_multi_to_single([1,4,6,7],[23,45,32,14]),[23,45,32,14])
[1, 4, 6, 7]
>>> convert_multi_to_single(convert_single_to_multi(21343,[23,45,32,14]),[23,45,32,14])
21343
-
如果您担心性能问题,那么您可以使用一些库,例如 pandas、numpy 等。
【讨论】:
【参考方案10】:n1=np.arange(90).reshape((3,3,-1))
print(n1)
print(n1.shape)
【讨论】:
以上是关于使用 Python 创建 3D 数组的主要内容,如果未能解决你的问题,请参考以下文章
在 Python 中从两个 1D 数组(2D 图)创建一个 2D 数组(3D 图)(用于计算希尔伯特谱)
有没有办法使用numpy从python中的2D数组构造3D数组?