xnx*_*xnx 19 python numpy data-structures
如果有的话,NumPy"结构化数组","记录数组"和"重新排列"之间的区别是什么?
该NumPy的文档 暗示,前两个是相同的:如果是这样,这是该对象的首选术语?
同样的文件说,(在页面的底部):你可以找到关于recarrays和结构化阵列(包括两者之间的区别)一些更多的信息在这里.这种差异有一个简单的解释吗?
hpa*_*ulj 11
记录/重新排列在实施中
https://github.com/numpy/numpy/blob/master/numpy/core/records.py
此文件中的一些相关引用
记录数组记录数组将结构化数组的字段显示为属性.重新排列几乎与标准数组(它已经支持命名字段)相同.最大的区别是它可以使用属性查找来查找字段,并使用记录构建它.
recarray是的子类ndarray(以同样的方式,matrix和masked 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.
Run Code Online (Sandbox Code Playgroud)
将唯一字段实现为属性行为的关键功能是__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)
Run Code Online (Sandbox Code Playgroud)
它首先它会尝试获取常规属性-比如.shape,.strides,.data,以及所有的方法(.sum,.reshape等).如果失败则会在dtype字段名称中查找名称.所以它实际上只是一个带有一些重新定义的访问方法的结构化数组.
我能说的最好record array,recarray也是一样的.
另一个文件显示了一些历史
https://github.com/numpy/numpy/blob/master/numpy/lib/recfunctions.py
用于操作结构化数组的实用程序的集合.大多数这些功能最初由John Hunter为matplotlib实现.为方便起见,它们已被重写和扩展.
此文件中的许多函数以:
if asrecarray:
output = output.view(recarray)
Run Code Online (Sandbox Code Playgroud)
您可以将recarray视图作为视图返回的事实显示该层的"薄"程度.
numpy历史悠久,并合并了几个独立的项目.我的印象是,这recarray是一个较旧的想法,结构化数组是基于通用化的当前实现dtype. recarrays似乎是为了方便和向后兼容而不是任何新的开发.但我必须研究github文件历史记录,以及任何最近的问题/拉取请求以确定.
简而言之,答案是您通常应该使用结构化数组而不是recarrays,因为结构化数组速度更快,并且recarrays的唯一优点是允许您编写arr.x而不是arr['x'],这是一个方便的快捷方式,但是如果您的列名也容易出错与numpy方法/属性冲突。
有关更详细的解释,请参见@jakevdp的书摘录。特别是,他指出,简单地访问结构化数组的列可能比访问recarray的列快20到30倍。但是,他的示例使用的是只有4行的非常小的数据框,并且不执行任何标准操作。
对于较大数据帧的简单操作,尽管结构化数组仍然更快,但差异可能会小得多。例如,这里是一个结构化的记录数组,每个数组有10,000行(代码是根据从@jpp answer 此处借来的数据帧创建数组的)。
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)))
Run Code Online (Sandbox Code Playgroud)
如果我们执行标准操作(例如将一列乘以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)
Run Code Online (Sandbox Code Playgroud)