使用 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.arrays 专为这种情况而设计:

 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 图)(用于计算希尔伯特谱)

如何在python中创建3D高度图

有没有办法使用numpy从python中的2D数组构造3D数组?

如何模糊点的 3D 数组,同时保持其原始值? (Python)

Python中的稀疏3d矩阵/数组?

Python NumPy - 3D 数组的角度切片