【问题标题】:numpy - Change/Specify dtypes of masked array columnsnumpy - 更改/指定掩码数组列的 dtypes
【发布时间】:2017-05-20 09:18:30
【问题描述】:

我有一个 csv 文件,其中包含我想作为掩码数组读取的大量数据。我已经使用以下方法完成了:

data=np.recfromcsv(filename,case_sensitive=True,usemask=True)

效果很好。但是,我的问题是数据要么是字符串,要么是整数,要么是浮点数。我现在要做的是将所有整数转换为浮点数,即将所有“1”转换为“1.0”等,同时保留其他所有内容。

此外,我正在寻找一个通用的解决方案。因此,由于 csv 文件(包括列数)发生变化,因此仅手动指定所需类型是行不通的。

我已经尝试过 astype,但由于该数组也有不起作用的字符串条目,还是我遗漏了什么?

谢谢。

【问题讨论】:

    标签: python arrays numpy types masked-array


    【解决方案1】:

    我没有使用过recfromcsv,但查看它的代码我发现它使用了np.genfromtxt,然后是一个屏蔽记录构造。

    我建议提供一个小样本 csv 文本(大约 3 行),并显示生成的 data。我们尤其需要看到dtype

    genfromtxt 开始可能也很有用,暂时跳过屏蔽数组的内容。我认为这不是在结构化数组中转换 dtype 的关键所在。

    无论如何,我们需要更具体的东西来探索。

    您无法就地更改结构化字段的 dtype。您必须使用新的 dtype 创建一个新数组,并将值从旧的复制到新的。

    import numpy.lib.recfunctions as rf
    

    有一些函数可以帮助改变结构化数组。

    ============

    我怀疑在调用 genfromtxt 时拼出 dtypes 比更改现有数组中的 dtype 更简单。

    您可以尝试使用dtype=None 和有限的行数进行一次读取,以获取列数和基数dtype。然后编辑它,根据需要用浮点数替换整数。现在用新的 dtype 阅读全文。如果您需要有关如何编辑 dtypes 的想法,请查看 recfunctions 代码。

    例如:

    In [504]: txt=b"""a, 1, 2, 4\nb, 6, 9, 10\nc, 4, 4, 3"""
    
    In [506]: arr = np.genfromtxt(txt.splitlines(), dtype=None, delimiter=',')
    In [507]: arr
    Out[507]: 
    array([(b'a', 1, 2, 4), (b'b', 6, 9, 10), (b'c', 4, 4, 3)], 
          dtype=[('f0', 'S1'), ('f1', '<i4'), ('f2', '<i4'), ('f3', '<i4')])
    In [508]: arr.dtype.descr
    Out[508]: [('f0', '|S1'), ('f1', '<i4'), ('f2', '<i4'), ('f3', '<i4')]
    

    粗略的 dtype 编辑器:

    def foo(tup):
        name, dtype=tup
        dtype = dtype.replace('S','U')
        dtype = dtype.replace('i','f')
        return name, dtype
    

    并将其应用于默认 dtype:

    In [511]: dt = [foo(tup) for tup in arr.dtype.descr]
    In [512]: dt
    Out[512]: [('f0', '|U1'), ('f1', '<f4'), ('f2', '<f4'), ('f3', '<f4')]
    
    In [513]: arr = np.genfromtxt(txt.splitlines(), dtype=dt, delimiter=',')
    In [514]: arr
    Out[514]: 
    array([('a', 1.0, 2.0, 4.0), ('b', 6.0, 9.0, 10.0), ('c', 4.0, 4.0, 3.0)], 
          dtype=[('f0', '<U1'), ('f1', '<f4'), ('f2', '<f4'), ('f3', '<f4')])
    
    In [522]: arr = np.recfromcsv(txt.splitlines(), dtype=dt, delimiter=',',case_sensitive=True,usemask=True,names=None)
    In [523]: arr
    Out[523]: 
    masked_records(
        f0 : ['a' 'b' 'c']
        f1 : [1.0 6.0 4.0]
        f2 : [2.0 9.0 4.0]
        f3 : [4.0 10.0 3.0]
        fill_value : ('N', 1.0000000200408773e+20, 1.0000000200408773e+20, 1.0000000200408773e+20)
                  )
    

    ======================

    astype 在目标 dtype 匹配时有效。例如,如果我使用 dtype=None 读取txt,然后使用派生的dt,它可以工作:

    In [530]: arr = np.genfromtxt(txt.splitlines(), delimiter=',',dtype=None)
    In [531]: arr
    Out[531]: 
    array([(b'a', 1, 2, 4), (b'b', 6, 9, 10), (b'c', 4, 4, 3)], 
          dtype=[('f0', 'S1'), ('f1', '<i4'), ('f2', '<i4'), ('f3', '<i4')])
    In [532]: arr.astype(dt)
    Out[532]: 
    array([('a', 1.0, 2.0, 4.0), ('b', 6.0, 9.0, 10.0), ('c', 4.0, 4.0, 3.0)], 
          dtype=[('f0', '<U1'), ('f1', '<f4'), ('f2', '<f4'), ('f3', '<f4')])
    

    arr.astype('U3,int,float,int') 也一样,它也有 4 个兼容字段。

    【讨论】:

      猜你喜欢
      • 2018-04-06
      • 1970-01-01
      • 2020-02-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-12
      • 1970-01-01
      相关资源
      最近更新 更多