Конвертировать элементы в замаскированной таблице астропии в np.nan
Рассмотрим простой процесс чтения файла данных с некоторыми недействительными записями. Это мое 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 ответа
Как отмечается, проблема в том, что NumPy MaskedArray.filled()
Кажется, что метод пытается преобразовать значение заполнения в соответствующий тип, прежде чем проверять, есть ли на самом деле что-нибудь для заполнения. Поскольку таблица в примере имеет int
столбец, это терпит неудачу в пределах NumPy (и Astropy. Таблица просто вызывает 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
Я не думаю, что это, в первую очередь, проблемная проблема, так как она работает с отдельными столбцами:
>>> 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, вы можете добавить эту проблему.
Это происходит довольно глубоко в 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)
Вырезать посредника? fill_values=[('INDEF', np.nan)])
похоже на работу.