numpy genfromtxt not applying missing_values

ぐ巨炮叔叔 提交于 2021-02-11 12:58:24

问题


I am currently struggling with a really simple problem, but cannot seem to solve it. You can reproduce the issue with the following file and code:

test.csv

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

code

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

output

[[ 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]]

Why does none of the versions for missing_values catch the -999 in the file and replace them with NaNs or something alike? I feel like this should be simple (and probably already answered somewhere on this website), but I cannot figure it out... Thanks for any help.


回答1:


There are two types of missing values. One is where the value is represent only by the delimiter. Default fill is nan, but we can define a separate fill:

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]])

Your case has a specific string:

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

The other answer suggests using usemask, returning a 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)

Looking at the code, I deduce that it's doing a string match, rather than a numeric one. It can also take one value per column (I don't think it does a per-row test):

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')])

Here I gave it dtype=None, so it returned a structured array.

missing_values can also be dict, but I haven't figured out what it expects.

I haven't figured out how to make it replace the missing values with something (such as from the filling_values).

You do the replace after load

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]])

It looks like genfromtxt constructs a converters from the missing and filling values, but I haven't followed the details. Here's a way of using our converter

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:


You need to add usemask=True.

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

Fill-in with NANs.

data = data.filled(np.nan)

Check for NANs.

np.isnan(data)

Output.

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


来源:https://stackoverflow.com/questions/64971218/numpy-genfromtxt-not-applying-missing-values

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!