向NumPy记录数组添加行

8
有没有一种方法可以将行添加到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个回答

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为一个全新的数组分配空间,并将旧数据复制到新位置。这自然是相当缓慢的,因此如果可能的话,应该尽量避免使用resizeappend。相反,从一开始就预先分配足够大的数组(即使比最终需要的稍微大一些)。

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: https://dev59.com/iUrSa4cB1Zd3GeqPVEzH#1731228
    """
    # 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.)])

仍然进行拆分,这次是按行。也许更好?


@Paul,问题是:“有没有更有效的方法来做这件事?”? - mjv

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接