以更简单的方式创建一个 np.array,并传输到 csv

create a np.array in a simpler way, and transferring to csv

我正在寻找更简单的代码来创建以下数组:

[[1. 1. 1.]
 [2. 1. 1.]
 [3. 1. 1.]
 [4. 1. 1.]
 [1. 2. 1.]
 [2. 2. 1.]
 [3. 2. 1.]
 [4. 2. 1.]
 [1. 3. 1.]
 [2. 3. 1.]
 [3. 3. 1.]
 [4. 3. 1.]
 [1. 1. 2.]
 [2. 1. 2.]
 [3. 1. 2.]
 [4. 1. 2.]
 [1. 2. 2.]
 [2. 2. 2.]
 [3. 2. 2.]
 [4. 2. 2.]
 [1. 3. 2.]
 [2. 3. 2.]
 [3. 3. 2.]
 [4. 3. 2.]]

我已经编写了以下代码来生成它,但绝对不是一个好代码。

import numpy as np

t1 = np.array([])
t2 = np.array([])

# creating the i column

for k in range (1,3):
    for j in range(1,4):
        x = np.array(list(range(1, 5)))
        y = np.append(t1, x)
        t1 = y

# creating the j column

for k in range(1,3):
    x = np.array(list(range(1, 4)))
    y = np.repeat(x, 4)
    t2 = np.append(t2, y)

# creating the k column

x = np.array(list(range(1, 3)))
t3 = np.repeat(x, 3*4)
new = np.transpose(np.vstack((t1, t2, t3)))

此外,在下一步中,我想将其导出到 csv 文件,使这些数字以这种形状存在(我的意思是我在 csv 文件中的第一列包括:1,2,3,1, 2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3 等接下来的两列) 我尝试使用 numpy.savetxt() 但它似乎只适用于一维和二维数组。

有什么建议吗?

itertools.product 非常适合您的用例:

from itertools import product
import pandas as pd

X = sorted(list(product([1,2,3,4], [1,2,3], [1,2])), key=lambda x: (x[2], x[1], x[0]))

pd.DataFrame(X).to_csv('output.csv', header=False, index=False)

输出:

[[1, 1, 1], [2, 1, 1], [3, 1, 1], [4, 1, 1], [1, 2, 1], [2, 2, 1], [3, 2, 1], [4, 2, 1], [1, 3, 1], [2, 3, 1], [3, 3, 1], [4, 3, 1], [1, 1, 2], [2, 1, 2], [3, 1, 2], [4, 1, 2], [1, 2, 2], [2, 2, 2], [3, 2, 2], [4, 2, 2], [1, 3, 2], [2, 3, 2], [3, 3, 2], [4, 3, 2]]

您可以使用 itertools 模块创建数组,然后使用 pandas 轻松将其导出到 csv 文件:

import itertools
import pandas as pd

# create the array of all combinations you showed
arr = list(itertools.product([1,2,3,4], [1,2,3], [1,2]))

# output the array to a csv file:
df = pd.DataFrame(arr).to_csv('filename.csv', header=False, index=False)

虽然 itertools.product 可能是最好的(我也想探索使用 np.meshgrid),但我们可以简化您的代码。

首先用列表理解制作 3 个列表。 np.append 重复使用会很慢。列表附加更好,但列表理解更紧凑。

In [94]: t1 = [np.arange(1,5) for k in range(2) for j in range(3)]
    ...: t2 = [np.repeat(np.arange(1,4),4) for k in range(2)]
    ...: t3 = np.repeat(np.arange(1,3), 3*4)

现在看看结果。值在那里,但形状不太正确。

In [95]: t1
Out[95]: 
[array([1, 2, 3, 4]),
 array([1, 2, 3, 4]),
 array([1, 2, 3, 4]),
 array([1, 2, 3, 4]),
 array([1, 2, 3, 4]),
 array([1, 2, 3, 4])]
In [96]: t2
Out[96]: 
[array([1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]),
 array([1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3])]
In [97]: t3
Out[97]: 
array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2])

但我们可以将它们压平。 np.ravel 会将列表转换为数组并将其展平。

In [98]: np.ravel(t1)
Out[98]: 
array([1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2,
       3, 4])

现在我们可以加入 stack。这就像 vstack 但让我们控制连接轴。

In [99]: np.stack((np.ravel(t1), np.ravel(t2), t3), axis=1)
Out[99]: 
array([[1, 1, 1],
       [2, 1, 1],
       [3, 1, 1],
       [4, 1, 1],
       [1, 2, 1],
       [2, 2, 1],
       [3, 2, 1],
       [4, 2, 1],
       [1, 3, 1],
       ...
       [3, 3, 2],
       [4, 3, 2]])

因为它是 2d,savetxt 就可以了:

In [100]: np.savetxt('test', Out[99], fmt='%5d')
In [101]: cat test
    1     1     1
    2     1     1
    3     1     1
    4     1     1
    1     2     1
   ...

===

itertools.product 生成正确的元组,但顺序相反:

In [108]: alist = list(itertools.product(range(1,3), range(1,4), range(1,5)))
In [109]: alist
Out[109]: 
[(1, 1, 1),
 (1, 1, 2),
 (1, 1, 3),
 (1, 1, 4),
 ...
 (2, 2, 4),
 (2, 3, 1),
 (2, 3, 2),
 (2, 3, 3),
 (2, 3, 4)]

但是当我们创建一个数组时,这很容易改变:

In [110]: np.array(alist)[:,::-1]
Out[110]: 
array([[1, 1, 1],
       [2, 1, 1],
       [3, 1, 1],
       [4, 1, 1],
       [1, 2, 1],
       ...
       [4, 2, 2],
       [1, 3, 2],
       [2, 3, 2],
       [3, 3, 2],
       [4, 3, 2]])

===

另一种选择 - meshgrid:

In [111]: x,y,z = np.meshgrid(np.arange(1,3), np.arange(1,4), np.arange(1,5), indexing='ij')
In [112]: x.shape
Out[112]: (2, 3, 4)
In [113]: y.shape
Out[113]: (2, 3, 4)
In [114]: x.ravel()
Out[114]: 
array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2])
In [115]: y.ravel()
Out[115]: 
array([1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3,
       3, 3])
In [116]: z.ravel()
Out[116]: 
array([1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2,
       3, 4])
In [117]: np.stack([z.ravel(), y.ravel(), x.ravel()], axis=1)
Out[117]: 
array([[1, 1, 1],
       [2, 1, 1],
       [3, 1, 1],
       [4, 1, 1],
       [1, 2, 1],
       ....

另一种组合 3 个数组的方法:

np.stack((z,y,x), axis=3).reshape(-1,3)

stack 步骤生成一个 (2, 3, 4, 3) 数组。

===

另一种方法(不解释):

arr = np.mgrid[1:3, 1:4, 1:5]
arr.transpose(1,2,3,0).reshape(-1,3)[:,::-1]