我正在将文件数据加载到numpy recarray中,然后用NaN填充已知的间隙。但是,我无法找到一种方法来增加重新排列中字段的大小,以便为填充的间隙重新分配数组。我的问题的一个例子(如下所示)引发了一个从较大到较小的形状广播的价值误差。
使用python 2.7.6.1,numpy 1.8.1-6
谢谢,Rob
import numpy as np
import numpy.ma as ma
a1 = np.arange(0,20,1)
a2 = np.arange(100,120,1)
X = np.recarray((20,), dtype=[('g', float), ('h', int)])
X['g'][:] = a1
X['h'][:] = a2
for afield in X.dtype.names:
Y = X[afield].copy(order='K')
for icnt in range(0,3):
Y = np.insert(Y, 5, np.nan, axis=0)
ma.resize(X[afield], (len(Y),) )
X[afield][:] = Y[:]
答案 0 :(得分:1)
你没有"扩展"你的recarray X.每个标签(名称/列)都不能扩展重组,这是你希望用ma.resize
做的。请注意ma.resize
返回具有新形状的新(蒙版)数组,而不更改传递给它的数组,但在您的代码中,您没有使用返回值。所以这条线没有做任何事情。澄清:
X[afield] = ma.resize(X[afield], (len(Y),) )
也不起作用,因为无法按标签扩展记录数组('列')。
如果要扩展重新排列,则需要一次性完成(使用np.lib.recfunctions
中的函数),因此添加一个全新的列或为所有现有列添加几个新记录。
话虽如此,为什么不试试这个:
>>> Y = np.arange(20, dtype=np.float)
>>> Ynan = np.insert(Y, (5,)*3, (np.nan,)*3)
>>> X = np.rec.fromarrays([Ynan, Ynan+100], names='g,h')
>>> X
rec.array([(0.0, 100.0), (1.0, 101.0), (2.0, 102.0), (3.0, 103.0),
(4.0, 104.0), (nan, nan), (nan, nan), (nan, nan), (5.0, 105.0),
(6.0, 106.0), (7.0, 107.0), (8.0, 108.0), (9.0, 109.0),
(10.0, 110.0), (11.0, 111.0), (12.0, 112.0), (13.0, 113.0),
(14.0, 114.0), (15.0, 115.0), (16.0, 116.0), (17.0, 117.0),
(18.0, 118.0), (19.0, 119.0)],
dtype=[('g', '<f8'), ('h', '<f8')])
请注意,您无法将第二列(标签&#39; h&#39;)转换为int,因为np.nan
是浮点类型。如果你尝试过,你会得到垃圾:
>>> X['h'].astype(np.int)
array([ 100, 101, 102,
103, 104, -9223372036854775808,
-9223372036854775808, -9223372036854775808, 105,
106, 107, 108,
109, 110, 111,
112, 113, 114,
115, 116, 117,
118, 119])
我认为你所追求的实际上是蒙面记录数组:
>>> import numpy.ma.mrecords as mrecords
>>>
>>> X = np.rec.fromarrays([Ynan, (Ynan+100).astype(np.int)], names='g,h')
>>> Z = np.ma.array(X, mask=np.isnan(Ynan))
>>> Z2 = Z.view(mrecords.mrecarray)
>>>
>>> Z2
masked_records(
g : [0.0 1.0 2.0 3.0 4.0 -- -- -- 5.0 6.0 7.0 8.0 9.0 10.0 11.0 12.0 13.0 14.0
15.0 16.0 17.0 18.0 19.0]
h : [100 101 102 103 104 -- -- -- 105 106 107 108 109 110 111 112 113 114 115
116 117 118 119]
fill_value : (1e+20, 999999)
)
>>>
>>> Z2['h']
masked_array(data = [100 101 102 103 104 -- -- -- 105 106 107 108 109 110 111 112 113 114 115
116 117 118 119],
mask = [False False False False False True True True False False False False
False False False False False False False False False False False],
fill_value = 999999)
正如您所看到的,&#34;列&#34; Z2具有所需的dtype(float和int),可以通过列名访问并隐藏一些数据。