Python 如何为每列使用不同的默认值初始化NumPy结构化数组?

Python 如何为每列使用不同的默认值初始化NumPy结构化数组?,python,arrays,python-2.7,numpy,matrix,Python,Arrays,Python 2.7,Numpy,Matrix,我试图初始化一个大小为(x,y)的NumPy结构化矩阵,其中x的值是~10^3,y的值是~10^6 矩阵的第一列是ID(整数),其余的是三元组(int8),其中三元组的每个成员都应该有不同的默认值 i、 e.假设默认值为[2,5,9]我想初始化以下矩阵: 0 2 5 9 2 5 9 2 5 9 ... 0 2 5 9 2 5 9 2 5 9 ... 0 2 5 9 2 5 9 2 5 9 ... 0 2 5 9 2 5 9 2 5 9 ... ... 这里的问题是,每列都有一个不同的唯一名称,

我试图初始化一个大小为(x,y)的NumPy结构化矩阵,其中x的值是
~10^3
,y的值是
~10^6

矩阵的第一列是ID(整数),其余的是三元组(int8),其中三元组的每个成员都应该有不同的默认值

i、 e.假设默认值为
[2,5,9]
我想初始化以下矩阵:

0 2 5 9 2 5 9 2 5 9 ...
0 2 5 9 2 5 9 2 5 9 ...
0 2 5 9 2 5 9 2 5 9 ...
0 2 5 9 2 5 9 2 5 9 ...
...
这里的问题是,每列都有一个不同的唯一名称,应该记录该名称

我能想到的初始化矩阵的最快方法是:

default_age       = 2
default_height    = 5
default_shoe_size = 9

columns = ["id", 
           "a_age", 
           "a_height", 
           "a_shoe_size", 
           "b_age", 
           "b_height", 
           "b_shoe_size",
           #...
           ]

y = len(columns)    
x = 10**4

# generate matrix
mat = numpy.zeros(shape=x,
                  dtype={"names"   : columns,
                         "formats" : ['i'] + ['int8'] * (len(columns) - 1)})
# fill the triplets with default values
for i in xrange(y/3):
    j = i * 3
    mat[mat.dtype.names[j+1]] = default_age
    mat[mat.dtype.names[j+2]] = default_height
    mat[mat.dtype.names[j+3]] = default_shoe_size
初始化这样一个矩阵的最快方法是什么


谢谢

您可以使用for循环填写默认值。例如,如果在字典中有默认值:

default_values = {
    "a_age": 3,
    "a_height": 5,
}
for column, value in default_values.items():
    mat[column] = value

您可以使用numpy提供的常规
平铺
列堆栈
构建数组,然后使用:

其中:

>>> mat
rec.array([(0, 2, 5, 9, 2, 5, 9), (0, 2, 5, 9, 2, 5, 9), (0, 2, 5, 9, 2, 5, 9),
       (0, 2, 5, 9, 2, 5, 9), (0, 2, 5, 9, 2, 5, 9), (0, 2, 5, 9, 2, 5, 9),
       (0, 2, 5, 9, 2, 5, 9), (0, 2, 5, 9, 2, 5, 9), (0, 2, 5, 9, 2, 5, 9),
       (0, 2, 5, 9, 2, 5, 9)], 
      dtype=[('id', '<i4'), ('a_age', 'i1'), ('a_height', 'i1'), ('a_shoe_size', 'i1'), ('b_age', 'i1'), ('b_height', 'i1'), ('b_shoe_size', 'i1')])
>>mat
记录数组([(0,2,5,9,2,5,9),(0,2,5,9,2,5,9),(0,2,5,9),(0,2,5,9),
(0, 2, 5, 9, 2, 5, 9), (0, 2, 5, 9, 2, 5, 9), (0, 2, 5, 9, 2, 5, 9),
(0, 2, 5, 9, 2, 5, 9), (0, 2, 5, 9, 2, 5, 9), (0, 2, 5, 9, 2, 5, 9),
(0, 2, 5, 9, 2, 5, 9)], 

dtype=[('id','这是我对示例的调整,经过调整使其运行

dt=np.dtype({"names": columns, "formats" : ['i'] + ['int8'] * (len(columns) - 1)})
mat=np.zeros((10,),dtype=dt)
for i in range(1,7,3):
    mat[dt.names[i]]=default_age
    mat[dt.names[i+1]]=default_height
    mat[dt.names[i+2]]=default_shoe_size
生产

array([(0, 2, 5, 9, 2, 5, 9), (0, 2, 5, 9, 2, 5, 9), (0, 2, 5, 9, 2, 5, 9),
       (0, 2, 5, 9, 2, 5, 9), (0, 2, 5, 9, 2, 5, 9), (0, 2, 5, 9, 2, 5, 9),
       (0, 2, 5, 9, 2, 5, 9), (0, 2, 5, 9, 2, 5, 9), (0, 2, 5, 9, 2, 5, 9),
       (0, 2, 5, 9, 2, 5, 9)], 
      dtype=[('id', '<i4'), ('collections.ChainMap(np.arange(6).reshape(3,2))[0]_age', 'i1'), ('a_height', 'i1'), ('a_shoe_size', 'i1'), ('b_age', 'i1'), ('b_height', 'i1'), ('b_shoe_size', 'i1')])
制作:

array([[2, 5, 9, 2, 5, 9],
       [2, 5, 9, 2, 5, 9],
       ...,
       [2, 5, 9, 2, 5, 9]])
添加到id列上

mat1=np.concatenate([np.zeros((x,1),int),mat1],1)
array([[0, 2, 5, 9, 2, 5, 9],
       [0, 2, 5, 9, 2, 5, 9],
       ...
       [0, 2, 5, 9, 2, 5, 9],
       [0, 2, 5, 9, 2, 5, 9]])
一个新的数据类型-全部为纯“int”:

dt1=np.dtype({"names"   : columns, "formats" : ['i'] + ['int'] * (len(columns) - 1)})
mat2=np.empty((x,),dtype=dt1)
如果操作正确,
mat1
数据应该与
mat2
的大小和字节顺序相同。在这种情况下,我可以“复制”它(实际上只是更改指针)

mat2
与前面的
mat
类似,只是
dtype
有点不同(使用
i4
而不是
i1
字段)

我没有运行时测试,部分原因是我不知道你的
x
y
值是什么样的

或者从中的答案来看,
np.ndarray
构造函数可用于使用预先存在的数据缓冲区创建新数组。它仍然需要使用
dt1
,即所有
i8
dtype

np.ndarray((x,), dt1, mat1)

此外,有关使用
视图
v.
astype
进行此转换的详细信息。

您可以使用枚举来表示列名

class Columns(Enum):
    id = 0
    a_age = 1
    a_height = 2
    a_shoe_size = 3
    b_age = 4
    b_height = 5
    b_shoe_size = 6
    ...

然后使用普通的数组初始化和访问语法,或者任何您想要使用的对象。您可以使用
列来代替列索引。例如,a_age
。有关枚举的详细信息,请检查此处

是否有理由不只使用数据帧?这里有些可疑。您正在创建一个2-d数组(具有形状
(x,len(columns))
),此数组的每个元素本身就是一个具有
len(columns)
字段的结构。你确定这是你想要的吗?(我猜你真的想要一维结构化数组。)虽然我还没有理解你的结构描述,但我的经验是,将数据逐字段复制到结构化数组通常是最快的方法。要么这样做,要么列出所有必需的元组。@Warren Weckesser你说得对-我的意思是创建一个1D结构化数组,编辑问题以反映这一点。谢谢!在开始之前关于“最快”,您应该给我们一个工作示例。您没有指定
x
y
,并且您的
mat[:,i+1]
索引将不适用于结构化数组。这与我建议的解决方案(性能方面)有何不同?您的解决方案在哪里?这是问题本身。
mat2.data=mat1.data
array([(0, 2, 5, 9, 2, 5, 9), (0, 2, 5, 9, 2, 5, 9), (0, 2, 5, 9, 2, 5, 9),
       (0, 2, 5, 9, 2, 5, 9), (0, 2, 5, 9, 2, 5, 9), (0, 2, 5, 9, 2, 5, 9),
       (0, 2, 5, 9, 2, 5, 9), (0, 2, 5, 9, 2, 5, 9), (0, 2, 5, 9, 2, 5, 9),
       (0, 2, 5, 9, 2, 5, 9)], 
      dtype=[('id', '<i4'), ('a_age', '<i4'), ('a_height', '<i4'), ('a_shoe_size', '<i4'), ('b_age', '<i4'), ('b_height', '<i4'), ('b_shoe_size', '<i4')])
np.array([tuple(row) for row in mat1],dtype=dt)
array([(0, 2, 5, 9, 2, 5, 9), (0, 2, 5, 9, 2, 5, 9), (0, 2, 5, 9, 2, 5, 9),
       (0, 2, 5, 9, 2, 5, 9), (0, 2, 5, 9, 2, 5, 9), (0, 2, 5, 9, 2, 5, 9),
       (0, 2, 5, 9, 2, 5, 9), (0, 2, 5, 9, 2, 5, 9), (0, 2, 5, 9, 2, 5, 9),
       (0, 2, 5, 9, 2, 5, 9)], 
      dtype=[('id', '<i4'), ('a_age', 'i1'), ('a_height', 'i1'), ('a_shoe_size', 'i1'), ('b_age', 'i1'), ('b_height', 'i1'), ('b_shoe_size', 'i1')])
np.ndarray((x,), dt1, mat1)
class Columns(Enum):
    id = 0
    a_age = 1
    a_height = 2
    a_shoe_size = 3
    b_age = 4
    b_height = 5
    b_shoe_size = 6
    ...