Python 更改tablar.tabarray或numpy.recarray的数据类型(dtype)

Python 更改tablar.tabarray或numpy.recarray的数据类型(dtype),python,numpy,Python,Numpy,我想将数据表示为Python中的电子表格。想到“好吧,肯定有人写了这样一个模块!”我去了PyPI,在那里我找到了Tabular,它用强大的数据操作功能包装了NumPy的重新排列。伟大的不幸的是,当涉及到字符串时,它看起来根本不像一个电子表格 >>> import tabular as tb >>> t = tb.tabarray(records=[('bork', 1, 3.5), ('stork', 2, -4.0)], names=['a','b','c'

我想将数据表示为Python中的电子表格。想到“好吧,肯定有人写了这样一个模块!”我去了PyPI,在那里我找到了Tabular,它用强大的数据操作功能包装了NumPy的重新排列。伟大的不幸的是,当涉及到字符串时,它看起来根本不像一个电子表格

>>> import tabular as tb
>>> t = tb.tabarray(records=[('bork', 1, 3.5), ('stork', 2, -4.0)], names=['a','b','c'])
>>> t
tabarray([('bork', 1, 3.5), ('stork', 2, -4.0)], 
      dtype=[('a', '|S5'), ('b', '<i8'), ('c', '<f8')])
>>> t['a'][0] = 'gorkalork, but not mork'
>>> t
tabarray([('gorka', 1, 3.5), ('stork', 2, -4.0)], 
      dtype=[('a', '|S5'), ('b', '<i8'), ('c', '<f8')])
>将表格作为tb导入
>>>t=tb.tabarray(记录=[('bork',1,3.5),('stork',2,-4.0)],名称=['a','b','c'])
>>>t
tabarray([('bork',1,3.5),('stork',2,-4.0)],
数据类型=[('a','S5'),('b','>>t.addrecords(('mushapushalussh',3,4.44))
tabarray([('gorka',1,3.5),('stork',2,-4.0),('musha',3,4.44)],

dtype=[('a','S5'),('b','我在这里不是想粗鲁,但你误解了什么是
numpy

你不要numpy,你要的是一个
dict

Numpy数组不是通用数据容器。它们是统一数据的内存高效容器。关键是要成为一个低级别的数据容器,它可以存储基本上没有内存开销的东西(即,100个64位浮点使用800字节的内存作为Numpy数组。它使用两倍的内存作为列表)

如果要存储非统一数据,则不要使用numpy数组


Python有一套非常丰富的内置数据结构。在这种情况下,dict或list就是您想要的。

我在这里并不是想粗鲁,但您误解了什么是
numpy

你不要numpy,你要的是一个
dict

Numpy数组不是通用数据容器。它们是统一数据的内存高效容器。关键是要成为一个低级别的数据容器,它可以存储基本上没有内存开销的东西(即,100个64位浮点使用800字节的内存作为Numpy数组。它使用两倍的内存作为列表)

如果要存储非统一数据,则不要使用numpy数组


Python有一套非常丰富的内置数据结构。在这种情况下,dict或list就是您想要的。

作为tablar的设计者之一……我不得不说,我认为第一个回答者基本上是一针见血的

哦,你痛惜的“截断”行为是NumPy的一个基本问题,Tablear就是基于这个问题的。但说它是一个应该修复的“bug”并不准确,它更像是一个“限制”,从一开始就呼应/强化了NumPy(和Tablear)的全部观点

正如第一位回答者所指出的,NumPy绝对要求数据结构的大小一致。一旦分配了给定数据类型的NumPy数组,该数组必须保持该数据类型——否则,必须初始化具有新内存的新数组。对于字符串数据类型,字符串的长度是数据类型的一个不可分割的固定部分数据类型——不能将长度为N的字符串数组“转换”为长度为M的字符串数组

固定数据类型对于NumPy比标准Python对象获得巨大性能提升的方式至关重要。这是因为,使用固定数据类型,NumPy对象知道分配给每个对象的字节数,并且可以在内存空间中“跳转”到给定项“应该”的位置与Python列表不同,它不必读取和处理所有插入项的内容。当然,这限制了自然可以是numpy数组的对象的种类……或者说,它限制了可以对numpy数组执行的操作的种类。与完全可变的Python列表不同(例如,您可以用任何其他python对象替换任何元素,而不会干扰列表中所有其他对象的内存分配),您不能将numpy数组的值变异为不同数据类型的对象,因为字节记帐是如何工作的?如果第n项突然大于数组中的所有其他项,那么所有剩余项的数据/位置会发生什么变化

你可能不喜欢NumPy的默认行为,因为当你试图使一个“非法”的破坏数据类型的赋值——也许您希望发出错误而不是静默截断?如果是这样,您应该在NumPy列表中发布,因为我认为这是一个比tablar更基本的问题——不管我们个人对错误处理的感受如何,我们都希望与NumPy所做的事情保持一致在这里

您可能也不喜欢tablar进行数据类型推断的方式。事实上,NumPy远离数据类型推断,基本上总是要求用户显式指定数据类型。这在某种意义上是好的,因为它要求用户考虑这些问题,但有时会很麻烦。tablar试图达到happy-medium在大多数情况下都很有用,但有时会失败——在这种情况下,可以通过指定与NumPy构造函数相同的关键字参数来覆盖默认值

当你说“1974年面向记录的数据库中常见的方法不可能是2011年Python的最新技术”时,我确实认为你是不对的事实上,NumPy内存管理的基础实际上与1970年代使用的工具完全相同——这可能令人惊讶,但大部分优化的NumPy仍然是建立在Fortran上的!即使在今天,也无法真正避免当时的内存分配问题,尽管NumPy确实提供了一个更干净、更简单的界面,大多数情况下但必须指出的是,如果您“愿意让系统做一些数据复制来简化我的代码”,那么NumPy和TABLABAR可能不适合您,因为静默数据复制及其所代表的一切都与这些包的设计意图背道而驰

所以问题变成了:你的目标是什么?如果你真的需要类似数组的操作的性能,那么就使用NumPy——在这种情况下,tablar提供了spreadsh
>>> t.addrecords(('mushapushalussh', 3, 4.44))
tabarray([('gorka', 1, 3.5), ('stork', 2, -4.0), ('musha', 3, 4.44)], 
      dtype=[('a', '|S5'), ('b', '<i8'), ('c', '<f8')])
>>> firstcol_long = firstcol.astype('|S15')
>>> firstcol_long
tabarray(['gorka', 'stork'], 
      dtype='|S15')
>>> firstcol_long[0] = 'morkapork'
>>> firstcol_long
tabarray(['morkapork', 'stork'], 
      dtype='|S15')
>>> t['a'] = firstcol_long
>>> t
tabarray([('morka', 1, 3.5), ('stork', 2, -4.0)], 
      dtype=[('a', '|S5'), ('b', '<i8'), ('c', '<f8')])
>>> 
>>> t = tb.tabarray(records=[('bork', 1, 3.5), ('stork', 2, -4.0)], dtype=[('a', str),('b', int),('c', float)])
>>> t
tabarray([('', 1, 3.5), ('', 2, -4.0)], 
      dtype=[('a', '|S0'), ('b', '<i8'), ('c', '<f8')])