【问题标题】:numpy genfromtxt not applying missing_valuesnumpy genfromtxt 不应用缺失值
【发布时间】:2021-03-06 08:00:20
【问题描述】:

我目前正在努力解决一个非常简单的问题,但似乎无法解决。您可以使用以下文件和代码重现该问题:

test.csv

2020081217,28.6
2020081218,24.7
2020081219,-999.0
2020081220,-999.0
2020081221,-999.0

代码

data = np.genfromtxt("C:/Users/col/Downloads/test.csv", delimiter=',', missing_values=["-999", "-999.0", -999, -999.0])
print(data)

输出

[[ 2.02008122e+09  2.86000000e+01]
 [ 2.02008122e+09  2.47000000e+01]
 [ 2.02008122e+09 -9.99000000e+02]
 [ 2.02008122e+09 -9.99000000e+02]
 [ 2.02008122e+09 -9.99000000e+02]]

为什么 missing_values 的所有版本都没有捕获文件中的 -999 并将其替换为 NaN 或类似的东西?我觉得这应该很简单(并且可能已经在本网站的某个地方回答了),但我无法弄清楚...感谢您的帮助。

【问题讨论】:

    标签: python numpy genfromtxt


    【解决方案1】:

    有两种类型的缺失值。一种是值仅由分隔符表示。默认填充是nan,但是我们可以定义一个单独的填充:

    In [93]: txt1="""2020081217,28.6
        ...: 2020081218,24.7
        ...: 2020081219,
        ...: 2020081220,
        ...: 2020081221,"""
    In [94]: np.genfromtxt(txt1.splitlines(),delimiter=',',encoding=None)
    Out[94]: 
    array([[2.02008122e+09, 2.86000000e+01],
           [2.02008122e+09, 2.47000000e+01],
           [2.02008122e+09,            nan],
           [2.02008122e+09,            nan],
           [2.02008122e+09,            nan]])
    In [95]: np.genfromtxt(txt1.splitlines(),delimiter=',',encoding=None,filling_val
        ...: ues=999)
    Out[95]: 
    array([[2.02008122e+09, 2.86000000e+01],
           [2.02008122e+09, 2.47000000e+01],
           [2.02008122e+09, 9.99000000e+02],
           [2.02008122e+09, 9.99000000e+02],
           [2.02008122e+09, 9.99000000e+02]])
    

    您的案例有一个特定的字符串:

    In [96]: txt="""2020081217,28.6
        ...: 2020081218,24.7
        ...: 2020081219,-999.0
        ...: 2020081220,-999.0
        ...: 2020081221,-999.0"""
    

    另一个答案建议使用 usemask,返回一个 masked_array:

    In [100]: np.genfromtxt(txt.splitlines(),delimiter=',',encoding=None, missing_values=-999.0, usemask=True)
    Out[100]: 
    masked_array(
      data=[[2020081217.0, 28.6],
            [2020081218.0, 24.7],
            [2020081219.0, --],
            [2020081220.0, --],
            [2020081221.0, --]],
      mask=[[False, False],
            [False, False],
            [False,  True],
            [False,  True],
            [False,  True]],
      fill_value=1e+20)
    

    查看代码,我推断它正在进行字符串匹配,而不是数字匹配。它也可以每列取一个值(我不认为它会进行每行测试):

    In [106]: np.genfromtxt(txt.splitlines(),delimiter=',',encoding=None, 
        missing_values=['2020081217','-999.0'], usemask=True, dtype=None)
    Out[106]: 
    masked_array(data=[(--, 28.6), (2020081218, 24.7), (2020081219, --),
                       (2020081220, --), (2020081221, --)],
                 mask=[( True, False), (False, False), (False,  True),
                       (False,  True), (False,  True)],
           fill_value=(999999, 1.e+20),
                dtype=[('f0', '<i8'), ('f1', '<f8')])
    

    这里我给了它dtype=None,所以它返回了一个结构化数组。

    missing_values 也可以是dict,但我还没弄清楚它的期望。

    我还没有弄清楚如何让它用某些东西(例如来自filling_values)替换缺失的值。

    加载后替换

    In [110]: data = np.genfromtxt(txt.splitlines(),delimiter=',',encoding=None)
    In [111]: data
    Out[111]: 
    array([[ 2.02008122e+09,  2.86000000e+01],
           [ 2.02008122e+09,  2.47000000e+01],
           [ 2.02008122e+09, -9.99000000e+02],
           [ 2.02008122e+09, -9.99000000e+02],
           [ 2.02008122e+09, -9.99000000e+02]])
    
    In [114]: data[data==-999] = np.nan
    In [115]: data
    Out[115]: 
    array([[2.02008122e+09, 2.86000000e+01],
           [2.02008122e+09, 2.47000000e+01],
           [2.02008122e+09,            nan],
           [2.02008122e+09,            nan],
           [2.02008122e+09,            nan]])
    

    看起来genfromtxt 从缺失值和填充值构造了一个converters,但我没有关注细节。这是使用我们的转换器的一种方式

    In [138]: converters={1:lambda x: np.nan if x=='-999.0' else float(x)}
    In [139]: data = np.genfromtxt(txt.splitlines(),delimiter=',',encoding=None, 
        converters=converters)
    In [140]: data
    Out[140]: 
    array([[2.02008122e+09, 2.86000000e+01],
           [2.02008122e+09, 2.47000000e+01],
           [2.02008122e+09,            nan],
           [2.02008122e+09,            nan],
           [2.02008122e+09,            nan]])
    

    【讨论】:

    • 感谢您的回复。我最终使用了我之前也做过的加载后替换,因为它是最快的选择。奇怪的是这没有更好的记录。
    【解决方案2】:

    您需要添加usemask=True

    data = np.genfromtxt("test.csv", delimiter=',', usemask=True, missing_values=-999.0)
    

    填写 NAN。

    data = data.filled(np.nan)
    

    检查 NAN。

    np.isnan(data)
    

    输出。

    array([[False, False],
       [False, False],
       [False,  True],
       [False,  True],
       [False,  True]])
    

    【讨论】:

    • 所以这个data 是一个masked_array,而您正在使用np.ma 方法将屏蔽值更改为nan
    猜你喜欢
    • 2014-10-09
    • 2015-10-04
    • 2011-04-15
    • 1970-01-01
    • 2013-11-29
    • 1970-01-01
    • 2012-05-10
    • 2013-01-14
    • 2019-09-27
    相关资源
    最近更新 更多