NumPy“record array”或“structured array”或“recarray”

vjrehmav  于 11个月前  发布在  其他
关注(0)|答案(2)|浏览(94)

NumPy“结构化数组”、“记录数组”和“重新数组”之间有什么区别?
NumPy docs意味着前两个是相同的:如果是,那么这个对象的首选术语是什么?
同样的文档说(在页面底部):你可以找到更多关于重新数组和结构化数组的信息(包括两者之间的区别)here

o2g1uqev

o2g1uqev1#

简单地说,你应该使用结构化数组而不是重新数组,因为结构化数组更快,重新数组的唯一优点是允许你写arr.x而不是arr['x'],这是一个方便的快捷方式,但如果你的列名与numpy方法/属性冲突,也容易出错。
请参阅@jakevdp的书中的excerpt以获得更详细的解释。特别是,他指出,简单地访问结构化数组的列可以比访问重新数组的列快20倍到30倍左右。然而,他的示例使用了一个只有4行的非常小的数组,并且没有执行任何标准操作。
对于更大的数组的简单操作,差异可能会小得多,尽管结构化数组仍然更快。例如,这里有一个结构化和记录数组,每个数组有10,000行(从@jpp answer here借用的数组创建数组的代码)。

n = 10_000
df = pd.DataFrame({ 'x':np.random.randn(n) })
df['y'] = df.x.astype(int)

rec_array = df.to_records(index=False)

s = df.dtypes
struct_array = np.array([tuple(x) for x in df.values], dtype=list(zip(s.index, s)))

字符串
如果我们做一个标准的操作,比如将一个列乘以2,那么结构化数组的速度大约快50%:

%timeit struct_array['x'] * 2
9.18 µs ± 88.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

%timeit rec_array.x * 2
14.2 µs ± 314 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

vm0i2vca

vm0i2vca2#

记录/重新排列在
https://github.com/numpy/numpy/blob/master/numpy/core/records.py
一些相关的报价从这个文件
记录数组记录数组将结构化数组的字段作为属性公开。recarray几乎与标准数组相同(已经支持命名字段)最大的区别是它可以使用属性查找来查找字段,并且它是使用记录构造的。
recarrayndarray的子类(与matrixmasked arrays相同)。但请注意,它的构造函数与np.array不同。它更像np.empty(size, dtype)

class recarray(ndarray):
    """Construct an ndarray that allows field access using attributes.
    This constructor can be compared to ``empty``: it creates a new record
       array but does not fill it with data.

字符串
将唯一字段实现为属性行为的关键函数是__getattribute____getitem__实现索引):

def __getattribute__(self, attr):
    # See if ndarray has this attr, and return it if so. (note that this
    # means a field with the same name as an ndarray attr cannot be
    # accessed by attribute).
    try:
        return object.__getattribute__(self, attr)
    except AttributeError:  # attr must be a fieldname
        pass

    # look for a field with this name
    fielddict = ndarray.__getattribute__(self, 'dtype').fields
    try:
        res = fielddict[attr][:2]
    except (TypeError, KeyError):
        raise AttributeError("recarray has no attribute %s" % attr)
    obj = self.getfield(*res)

    # At this point obj will always be a recarray, since (see
    # PyArray_GetField) the type of obj is inherited. Next, if obj.dtype is
    # non-structured, convert it to an ndarray. If obj is structured leave
    # it as a recarray, but make sure to convert to the same dtype.type (eg
    # to preserve numpy.record type if present), since nested structured
    # fields do not inherit type.
    if obj.dtype.fields:
        return obj.view(dtype=(self.dtype.type, obj.dtype.fields))
    else:
        return obj.view(ndarray)


它首先尝试获取一个常规属性-像.shape.strides.data,以及所有的方法(.sum.reshape等)。如果失败,它然后在dtype字段名称中查找名称。所以它实际上只是一个具有一些重新定义的访问方法的结构化数组。
record arrayrecarray是一样的。
另一份文件显示了
https://github.com/numpy/numpy/blob/master/numpy/lib/recfunctions.py
用于操作结构化数组的实用程序集合。这些函数中的大多数最初由John Hunter为matplotlib实现。为了方便起见,它们已被重写和扩展。
此文件中的许多函数都以以下结尾:

if asrecarray:
        output = output.view(recarray)


您可以将数组返回为recarray视图,这一事实表明这一层是多么的“薄”。
numpy有很长的历史,并合并了几个独立的项目。我的印象是,recarray是一个老的想法,和结构化数组,目前的实现,建立在一个广义的dtyperecarrays似乎是为了方便和向后兼容,而不是任何新的发展。但我必须研究github文件的历史,和任何最近的问题/拉请求,以确保。

相关问题