【问题标题】:Construct a numpy array with dtypes column wise构造一个具有 dtypes 列的 numpy 数组
【发布时间】:2020-05-08 23:27:16
【问题描述】:

所以我真的放弃了。我想用shape(10000000,3) 预先分配一个巨大的2d-numpy 数组,每列有一个特定的dtype

例子:

    a         b        c     
 -------- --------- -------- 
  uint32   float32   uint8   
  ------   ------    ------  
  90       2.43      4       
  100      2.42      2       
  123      2.33      1   

所以from the docs 我可以像这样创建一个二维数组:

arr = np.zeros((4,3))                                                                                                                                                                                          
arr                                                                                                                                                                                                            
Out[6]: 
array([[0., 0., 0.],
       [0., 0., 0.],
       [0., 0., 0.],
       [0., 0., 0.]])

到目前为止还不错,但是 dtypes 呢?

In [16]: arr.dtype                                                                                                                                                                                                     
Out[16]: dtype('float64')

所有浮点数 - 所以让我们定义 dtype:

dtype_L1 = np.dtype({'names': ['a', 'b', 'c'], 
               'formats': [np.uint32, np.float32, np.uint8]})

并比较两者:

In [25]: arr_dtype = np.zeros((4,3), dtype=dtype_L1)                                                                                                                                                                   

In [26]: arr = np.zeros((4,3))                                                                                                                                                                                         

In [27]: arr[0,0]                                                                                                                                                                                                      
Out[27]: 0.0

In [28]: arr_dtype[0,0]                                                                                                                                                                                                
Out[28]: (0, 0., 0)

In [29]: type(arr_dtype[0,0])                                                                                                                                                                                          
Out[29]: numpy.void

In [30]: type(arr[0,0])                                                                                                                                                                                                
Out[30]: numpy.float64

In [31]: arr.shape                                                                                                                                                                                                     
Out[31]: (4, 3)

In [32]: arr_dtype.shape                                                                                                                                                                                               
Out[32]: (4, 3)

所以-我不明白为什么arr_dtypearr 不同,只是每列其他dtype。有人可以指导一个方向吗?看起来我正在创建一个维度太高的数组..:

**更新:一维太深..? **

>>> arr[0,0]
0 ## Correct

>>> arr_dtype[0,0]
(0, 0., 0) 

它真的在这里保存了 dtyped 数组?!深入一维:

>>> type(arr_dtype[0,0][0])
<class 'numpy.uint32'>
>>> type(arr_dtype[0,0][1])
<class 'numpy.float32'>
>>> type(arr_dtype[0,0][2])
<class 'numpy.uint8'>
# all good - But one level too deep.
  • 预期:numpy 正在建立一个 4x3 矩阵,其中 每个元素 是一个数字。 12 个数字完全正确。
  • 观察到:numpy 正在建立一个 4x3 矩阵,其中 每个元素 是一个 shape (3,) 结构。所以我有 4x3x3 字段 = 36 个数字。

那么是否可以通过其他方式申请dtype

最终解决方案

您基本上需要决定什么更重要:节省空间还是将所有数据集中到一个array?一个数组只能有一个 dtype。因此,如果您需要不同的数据类型,请选择 Y 轴长度相同的多个数组。否则,像arr_dtype = np.zeros((4,3), dtype=np.float32) 一样创建它,并确保将dtype 设置为每个数组的正确类型。感谢 cmets!

【问题讨论】:

  • arr_dtypearr 具有不同的形状和数据类型。一个的字段与另一个的列不同。只有复合数据类型允许混合数据类型。
  • 对不起@hpaulj,但你的评论并没有帮助我前进。我想要一个简单的数组:3 列,4 行。最零列的类型为unit32,第一列为float32,第二列为unit8。我认为如果我能看到如何做到这一点会更清楚。
  • 不能有一个“简单”的数组,每列都有不同的数据类型。
  • @hpaulj 好的...那么我怎样才能使用三种不同的按列 dtypes 获得一些 structured array 呢?我仍然试图弄清楚为什么代码是错误的(根据你的评论)。所以从one of many examples看来,这里应用的dtype属性是正确的?很高兴得到建议。
  • dt = np.dtype(...); arr = np.zeros((2000,), dtype=dt) 生成结构化数组。 arr=np.zeros((2000,3), dtype=float) 制作二维浮点数组。当一个或多个列是 string dtype 和/或 float 和 int 的混合时,结构化数组最有意义。它实际上只是创建 3 个单独的数组的替代方法,每个数组都有自己的 dtype。您无法跨字段进行数学运算,因此使用复合 dtype 几乎没有计算优势。

标签: python-3.x numpy multidimensional-array numpy-ndarray


【解决方案1】:

将数组中的一行视为单个元素。这实际上就是复合 dtype 为您所做的。您可以将 dtype 定义为

d1 = np.dtype({'names': ['a', 'b', 'c'], 
               'formats': [np.uint32, np.float32, np.uint8]})

这意味着您有一个 3 列数组。你用类似的东西分配它

arr = np.empty(10000, dtype=d1)

zeros 替换为您认为合适的empty。结果实际上是一个(10000, 3) 数组,尽管它显示为(10000,) 数组。您可以使用字段名称将视图提取到各个列,例如:

arr['a']

【讨论】:

  • 是的,但我理解正确,这实际上并不是一个真正的二维数组。它是一维数组的 3 倍,因此,对同一行中不同列的计算效率不高(虽然可以使用 [] getter 访问它们。
  • @gies0r。您的内存布局完全符合您的预期,并且从 numpy 1.16 开始,访问这些字段会返回一个真实视图,其中的步幅经过适当调整以跳过其余字段。这并不比获取真实 3D 数组的切片效率低
  • @gies0r。话虽如此,根据操作,维护统一类型的 Nx3 数组或 3 个单独的连续数组可能更有效。在这些情况下,连续性通常比任何事情都重要,甚至是类型转换。
  • 我的目标是回答如何创建类似数据框的数组的问题,而不是指出不这样做的原因。毕竟,这是你问的。
  • 我同意您的所有观点,是的,您的解决方案按预期工作。我假设它应该与pd.DataFrame 非常相似,但我认为在这里值得一提的是,创建一个大数组或在同一个 Y 轴上创建多个较小的数组之间的区别在于它们的用法和计算时间。尽管如此,您的解决方案在不需要的情况下仍然有效 - 所以我赞成它。
【解决方案2】:

arr_dtype 是一个结构化数组,其中包含可以为它们分配不同数据类型的字段(此处为 'a''b''c')。结构化数组的每个元素都是一个结构,结构的元素(对应于字段)可以有不同的数据类型(技术上,arr_dtype 的元素都是相同的类型,在这种情况下是numpy.void 结构。它是元素numpy.void 对象中可以有不同的数据类型。换句话说,numpy 数组元素总是同质的)。另一方面,arr 是一个非结构化数组,所有元素都具有相同的数据类型。非结构化数组的每个元素都是一个对象(在本例中为数字)。

检查您的输出以查看差异:

arr_dtype
[[(0, 0., 0) (0, 0., 0) (0, 0., 0)]
 [(0, 0., 0) (0, 0., 0) (0, 0., 0)]
 [(0, 0., 0) (0, 0., 0) (0, 0., 0)]
 [(0, 0., 0) (0, 0., 0) (0, 0., 0)]]

arr
[[0. 0. 0.]
 [0. 0. 0.]
 [0. 0. 0.]
 [0. 0. 0.]]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    • 2015-09-11
    • 2017-05-20
    • 2016-11-01
    • 2018-10-12
    • 2019-04-03
    • 2018-04-06
    相关资源
    最近更新 更多