向NumPy记录数组追加行
有没有办法给一个NumPy的rec.array()添加一行?比如说,
x1=np.array([1,2,3,4])
x2=np.array(['a','dd','xyz','12'])
x3=np.array([1.1,2,3,4])
r = np.core.records.fromarrays([x1,x2,x3],names='a,b,c')
append(r,(5,'cc',43.0),axis=0)
最简单的方法是把所有的列提取出来,变成nd.array()类型,然后把每一列的元素单独添加,再重新构建rec.array()。不过,这种方法在内存使用上不太高效。有没有其他方法可以在不拆分和重建rec.array()的情况下做到这一点?
谢谢,
Eli
3 个回答
0
在@unutbu的回答基础上,我分享一个更通用的函数,可以添加任意数量的行:
def append_rows(arrayIN, NewRows):
"""Append rows to numpy recarray.
Arguments:
arrayIN: a numpy recarray that should be expanded
NewRows: list of tuples with the same shape as `arrayIN`
Idea: Resize recarray in-place if possible.
(only for small arrays reasonable)
>>> arrayIN = np.array([(1, 'a', 1.1), (2, 'dd', 2.0), (3, 'x', 3.0)],
dtype=[('a', '<i4'), ('b', '|S3'), ('c', '<f8')])
>>> NewRows = [(4, '12', 4.0), (5, 'cc', 43.0)]
>>> append_rows(arrayIN, NewRows)
>>> print(arrayIN)
[(1, 'a', 1.1) (2, 'dd', 2.0) (3, 'x', 3.0) (4, '12', 4.0) (5, 'cc', 43.0)]
Source: http://stackoverflow.com/a/1731228/2062965
"""
# Calculate the number of old and new rows
len_arrayIN = arrayIN.shape[0]
len_NewRows = len(NewRows)
# Resize the old recarray
arrayIN.resize(len_arrayIN + len_NewRows, refcheck=False)
# Write to the end of recarray
arrayIN[-len_NewRows:] = NewRows
评论
我想强调的是,如果你对数组的最终大小有个大概念,提前分配一个足够大的数组是最合理的解决方案!这样做还可以节省很多时间。
0
np.core.records.fromrecords(r.tolist()+[(5,'cc',43.)])
这次它还是会分开,不过是按行来分。这样可能更好一些?
7
你可以直接在原地调整numpy数组的大小。这比先转换成列表再转回numpy数组要快,而且占用的内存也更少。
print (r.shape)
# (4,)
r.resize(5)
print (r.shape)
# (5,)
r[-1] = (5,'cc',43.0)
print(r)
# [(1, 'a', 1.1000000000000001)
# (2, 'dd', 2.0)
# (3, 'xyz', 3.0)
# (4, '12', 4.0)
# (5, 'cc', 43.0)]
如果内存不够,无法在原地扩展数组,那么调整大小(或添加元素)的操作可能会迫使NumPy为一个全新的数组分配空间,并把旧数据复制到新位置。这样做自然会比较慢,所以尽量避免使用resize
或append
。相反,最好一开始就预先分配足够大的数组(即使比最终需要的稍大一些)。