我有一个现有的两列numpy数组,我需要添加列名。通过via dtype
传递这些内容适用于下面 Block 1 中显示的玩具示例。但是,使用我的实际数组,如 Block 2 所示,同样的方法是出现意外(对我而言)更改数组维度的副作用。
如何将我的实际数组(下面第二个块中名为Y
的数组)转换为具有命名列的数组,就像我在第一个块中为数组A
所做的那样?
第1区:(A
列未命名重塑维度)
import numpy as np
A = np.array(((1,2),(3,4),(50,100)))
A
# array([[ 1, 2],
# [ 3, 4],
# [ 50, 100]])
dt = {'names':['ID', 'Ring'], 'formats':[np.int32, np.int32]}
A.dtype=dt
A
# array([[(1, 2)],
# [(3, 4)],
# [(50, 100)]],
# dtype=[('ID', '<i4'), ('Ring', '<i4')])
第2块:(命名我实际数组的列Y
,重塑其维度)
import numpy as np
## Code to reproduce Y, the array I'm actually dealing with
nRings = 3
nn = [[nRings+1-n] * n for n in range(nRings+1)]
RING = reduce(lambda x, y: x+y, nn)
ID = range(1,len(RING)+1)
X = numpy.array([ID, RING])
Y = X.T
Y
# array([[1, 3],
# [2, 2],
# [3, 2],
# [4, 1],
# [5, 1],
# [6, 1]])
## My unsuccessful attempt to add names to the array's columns
dt = {'names':['ID', 'Ring'], 'formats':[np.int32, np.int32]}
Y.dtype=dt
Y
# array([[(1, 2), (3, 2)],
# [(3, 4), (2, 1)],
# [(5, 6), (1, 1)]],
# dtype=[('ID', '<i4'), ('Ring', '<i4')])
## What I'd like instead of the results shown just above
# array([[(1, 3)],
# [(2, 2)],
# [(3, 2)],
# [(4, 1)],
# [(5, 1)],
# [(6, 1)]],
# dtype=[('ID', '<i4'), ('Ring', '<i4')])
答案 0 :(得分:2)
首先因为你的问题要求给数组命名,我觉得有必要指出使用&#34;结构化数组&#34;为了给出名字可能不是最好的方法。当我们使用表格时,我们经常喜欢为行/列命名,如果是这种情况,我建议您尝试类似pandas的内容,这很棒。如果您只想在代码中组织一些数据,那么数组字典通常比结构化数组好得多,例如,您可以这样做:
Y = {'ID':X[0], 'Ring':X[1]}
如果你想使用结构化数组,那么在我看来这是最明智的方法:
import numpy as np
nRings = 3
nn = [[nRings+1-n] * n for n in range(nRings+1)]
RING = reduce(lambda x, y: x+y, nn)
ID = range(1,len(RING)+1)
X = np.array([ID, RING])
dt = {'names':['ID', 'Ring'], 'formats':[np.int, np.int]}
Y = np.zeros(len(RING), dtype=dt)
Y['ID'] = X[0]
Y['Ring'] = X[1]
答案 1 :(得分:1)
尝试重写X的定义:
X = np.array(zip(ID, RING))
然后你不需要定义Y = X.T
答案 2 :(得分:1)
您是否完全确定A
和Y
的输出?我使用Python 2.7.6和numpy 1.8.1获得了不同的东西。
A
的初始输出与您的初始输出相同。为第一个示例运行以下代码后
dt = {'names':['ID', 'Ring'], 'formats':[np.int32, np.int32]}
A.dtype=dt
数组A
的内容实际上是
array([[(1, 0), (3, 0)],
[(2, 0), (2, 0)],
[(3, 0), (2, 0)],
[(4, 0), (1, 0)],
[(5, 0), (1, 0)],
[(6, 0), (1, 0)]],
dtype=[('ID', '<i4'), ('Ring', '<i4')])
这对我来说比你添加的输出更有意义,因为dtype
确定数组中每个元素的数据类型,而新定义声明每个元素应该包含两个字段,所以它确实如此,但是第二个字段的值设置为0,因为第二个字段没有预先存在的值。
但是,如果您想为现有数组创建numpy group列,以便每行只包含一个元素,但每个元素包含两个字段,则可以引入一个小代码更改。
由于需要使用元组将numpy组元素转换为更复杂的数据类型,因此可以通过创建新数组并将现有数组的每一行转换为元组来实现。这是一个简单的工作示例
import numpy as np
A = np.array(((1,2),(3,4),(50,100)))
dt = np.dtype([('ID', np.int32), ('Ring', np.int32)])
B = np.array(list(map(tuple, A)), dtype=dt)
使用这段短代码,数组B
变为
array([(1, 2), (3, 4), (50, 100)],
dtype=[('ID', '<i4'), ('Ring', '<i4')])
要使B
成为2D数组,只需编写
B.reshape(len(B), 1) # in this case, even B.size would work instead of len(B)
对于第二个例子,需要做类似的事情才能使Y成为结构化数组:
Y = np.array(list(map(tuple, X.T)), dtype=dt)
在为第二个例子执行此操作后,数组Y看起来像这样
array([(1, 3), (2, 2), (3, 2), (4, 1), (5, 1), (6, 1)],
dtype=[('ID', '<i4'), ('Ring', '<i4')])
您可以注意到输出与您期望的输出不同,但是这个输出更简单,因为您可以只编写{{1}而不是编写Y[0,0]
来获取第一个元素。 }。要同时制作此数组2D,您也可以使用Y[0]
,就像使用reshape
一样。
答案 3 :(得分:1)
这是因为Y不是C_CONTIGUOUS,你可以Y.flags
检查:
C_CONTIGUOUS : False
F_CONTIGUOUS : True
OWNDATA : False
WRITEABLE : True
ALIGNED : True
UPDATEIFCOPY : False
您可以先致电Y.copy()
或Y.ravel()
:
dt = {'names':['ID', 'Ring'], 'formats':[np.int32, np.int32]}
print Y.ravel().view(dt) # the result shape is (6, )
print Y.copy().view(dt) # the result shape is (6, 1)
答案 4 :(得分:1)
store-different-datatypes-in-one-numpy-array 另一个页面包括一个很好的解决方案,可以将名称添加到一个可以用作列的数组 例如:
r = np.core.records.fromarrays([x1,x2,x3],names='a,b,c')
# x1, x2, x3 are flatten array
# a,b,c are field name