Конвертировать элементы в замаскированной таблице астропии в np.nan - PullRequest
0 голосов
/ 03 мая 2018

Рассмотрим простой процесс чтения файла данных с некоторыми недействительными записями. Это мой test.dat файл:

16        1035.22  1041.09    24.54     0.30     1.39     0.30     1.80     0.30     2.26     0.30     1.14     0.30     0.28     0.30   0.2884
127        824.57  1105.52    25.02     0.29     0.87     0.29     1.30     0.29     2.12     0.29     0.66     0.29     0.10     0.29   0.2986
182       1015.83   904.93    INDEF     0.28     1.80     0.28     1.64     0.28     2.38     0.28     1.04     0.28     0.06     0.28   0.3271
185       1019.15  1155.09    24.31     0.28     1.40     0.28     1.78     0.28     2.10     0.28     0.87     0.28     0.35     0.28   0.3290
192       1024.80  1045.57    24.27     0.27     1.24     0.27     2.01     0.27     2.40     0.27     0.90     0.27     0.09     0.27   0.3328
197       1035.99   876.04    24.10     0.27     1.23     0.27     1.52     0.27     2.59     0.27     0.45     0.27     0.25     0.27   0.3357
198       1110.80  1087.97    24.53     0.27     1.49     0.27     1.71     0.27     2.33     0.27     0.22     0.27     0.00     0.27   0.3362
1103      1168.39  1065.97    24.35     0.27     1.28     0.27     1.29     0.27     2.68     0.27     0.43     0.27     0.26     0.27   0.3388

А это код для его чтения и замены «плохих» значений (INDEF) на число с плавающей точкой (99.999)

import numpy as np
from astropy.io import ascii

data = ascii.read("test.dat", fill_values=[('INDEF', '0')])
data = data.filled(99.999)

Это работает просто отлично, но если я вместо этого попытаюсь заменить неправильные значения на np.nan (т.е. я использую строку data = data.filled(np.nan)), я получу:

ValueError: cannot convert float NaN to integer

почему это так и как я могу обойти это?

Ответы [ 4 ]

0 голосов
/ 04 мая 2018

Как уже отмечалось, проблема в том, что метод numpy MaskedArray.filled(), по-видимому, пытается преобразовать значение заполнения в соответствующий тип, прежде чем проверять, есть ли на самом деле что-либо для заполнения. Так как в таблице в этом примере есть столбец int, в numpy это не получится (а astropy.Table просто вызывает метод filled() для каждого столбца).

Это должно работать:

In [44]: def fill_cols(tbl, fill=np.nan, kind='f'):
    ...:     """
    ...:     In-place fill of ``tbl`` columns which have dtype ``kind``
    ...:     with ``fill`` value.
    ...:     """
    ...:     for col in tbl.itercols():
    ...:         if col.dtype.kind == kind:
    ...:             col[...] = col.filled(fill)
    ...: 

In [45]: t = simple_table(masked=True)

In [46]: t
Out[46]: 
<Table masked=True length=3>
  a      b     c  
int64 float64 str1
----- ------- ----
   --     1.0    c
    2     2.0   --
    3      --    e

In [47]: fill_cols(t)

In [48]: t
Out[48]: 
<Table masked=True length=3>
  a      b     c  
int64 float64 str1
----- ------- ----
   --     1.0    c
    2     2.0   --
    3     nan    e
0 голосов
/ 03 мая 2018

Вырезать посредника? fill_values=[('INDEF', np.nan)]) кажется, работает.

0 голосов
/ 03 мая 2018

Я не думаю, что это в первую очередь проблема с кучкой символов, так как она работает с отдельными столбцами:

>>> data['col4'].filled(np.nan)
<Column name='col4' dtype='float64' length=8>
24.54
25.02
  nan
24.31
24.27
24.1
24.53
24.35

но вы все еще не можете построить Table из этого -

Table([data[n].filled(np.nan) for n in data.colnames])

вызывает ту же ошибку в np.ma.core. Вы можете явно установить

data['col4'] = data['col4'].filled(np.nan)

но это, очевидно, позволяет таблице потерять метод .filled() ... Я не очень хорошо знаком с замаскированными массивами и таблицами, но, поскольку вы уже подали на Github связанную с проблему , вы можете добавить эту проблему.

0 голосов
/ 03 мая 2018

Это происходит довольно глубоко в numpy, в numpy.ma.filled. значения заполнения должны быть скалярами, в основном.

Грязное решение, которое заполняется с помощью nan и возвращает таблицу, может выглядеть так:

import numpy as np
from astropy.io import ascii
from astropy.table import Table

def fill_with_nan(t):
    arr = t.as_array()
    arr_list = arr.tolist()
    arr = np.array(arr_list)
    arr[np.equal(arr, None)] = np.nan
    arr = np.array(arr.tolist())
    return Table(arr)


data = ascii.read("test.dat", fill_values=[('INDEF', '0')])
data = fill_with_nan(data)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...