numpy genfromtxt - отсутствующие данные против неверных данных

Я использую numpy genfromtxt, и мне нужно определить как отсутствующие данные, так и неверные данные. В зависимости от пользовательского ввода я могу захотеть отбросить неверное значение или вызвать ошибку. По сути, я хочу рассматривать отсутствующие и неверные данные как одно и то же.

Скажем, у меня есть такой файл, где столбцы имеют типы данных date, int, float

date,id,value
2017-12-4,0,       # BAD. missing data
2017-12-4,1,XYZ    # BAD. value should be float, not string. 
2017-12-4,2,1.0    # good
2017-12-4,3,1.0    # good
2017-12-4,4,1.0    # good

Я хотел бы обнаружить оба. Итак, я делаю это

dtype=(np.dtype('<M8[D]'), np.dtype('int64'), np.dtype('float64'))
result = np.genfromtxt(filename, delimiter=',', dtype=dtype, names=True, usemask=True, usecols=('date', 'id', 'value'))

И результат такой

masked_array(data=[(datetime.date(2017, 12, 4), 0, --),
               (datetime.date(2017, 12, 4), 1, nan),
               (datetime.date(2017, 12, 4), 2, 1.0),
               (datetime.date(2017, 12, 4), 3, 1.0),
               (datetime.date(2017, 12, 4), 4, 1.0)],
         mask=[(False, False,  True), (False, False, False),
               (False, False, False), (False, False, False),
               (False, False, False)],
   fill_value=('NaT', 999999, 1.e+20),
        dtype=[('date', '<M8[D]'), ('id', '<i8'), ('value', '<f8')])

Я думал, что весь смысл masked_array в том, что он может обрабатывать отсутствующие данные И неверные данные. Но здесь он обрабатывает только отсутствующие данные.

result['value'].mask

возвращается

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

Плохие данные на самом деле все равно попадали в массив, так как nan. Я надеялся, что маска даст мне True True False False False.

Чтобы я понял, что у нас неправильное значение во 2-й строке, мне нужно выполнить дополнительную работу, например проверить наличие nan.

another_mask = np.isnan(result['value'])
good_result = result['value'][~another_mask]

Наконец, это возвращает

masked_array(data=[1.0, 1.0, 1.0],
         mask=[False, False, False],
   fill_value=1e+20)

Это работает, но я чувствую, что делаю что-то не так. Весь смысл maskedArray заключается в том, чтобы найти отсутствующие и неверные данные, но я каким-то образом использую его только для поиска недостающих данных. И мне нужен собственный чек, чтобы найти неверные данные. Чувствует себя уродливым и не питоническим.

Есть ли способ найти и то, и другое одновременно?


person user3240688    schedule 14.12.2020    source источник
comment
Мне не нравится это «непитоновское» понятие. Если это работает, это pythonic. Другое дело, использует ли он в полной мере такую ​​сложную функцию, как genfromtxt. Я не могу ссылаться на это прямо сейчас, но не так давно я боролся с этим в другом SO. Кажется, что функция хорошо заполняет пропущенные значения. Менее ясно, полностью ли функциональна замаскированная часть или даже то, что она должна делать. Это плохо документировано   -  person hpaulj    schedule 15.12.2020
comment
Как насчет заполнения nan, а затем использования np.ma.masked_invalid для маскировки всех nan. Вы не получите ни одного брауни-поинта за выполнение всего в genfromtxt.   -  person hpaulj    schedule 15.12.2020
comment
stackoverflow.com/questions/64971218/ (может быть дубликатом)   -  person hpaulj    schedule 15.12.2020
comment
Когда вы создаете MaskedArray, вы должны указать, что нужно маскировать. Этот класс не имеет критерия маскирования по умолчанию. genfrontxt не документирует использование этого флага.   -  person hpaulj    schedule 15.12.2020
comment
заполнение nan - мое последнее средство. Причина, по которой мне не нравится nan, заключается в том, что nan может быть реальным числом. Но и строка, и пустое пространство являются примерами неверных значений. Я хотел бы различать nan и bad_values. Вот почему я подумал, что masked_array будет идеей.   -  person user3240688    schedule 15.12.2020


Ответы (1)


Играем с простым вводом:

In [143]: txt='''1,2
     ...: 3,nan
     ...: 4,foo
     ...: 5,
     ...: '''.splitlines()
In [144]: txt
Out[144]: ['1,2', '3,nan', '4,foo', '5,']

Указав конкретную строку как «отсутствующую» (это может быть список?), Я могу «замаскировать» ее вместе с пустой:

In [146]: np.genfromtxt(txt,delimiter=',', missing_values='foo', 
       usemask=True, usecols=1)
Out[146]: 
masked_array(data=[2.0, nan, --, --],
             mask=[False, False,  True,  True],
       fill_value=1e+20)

Похоже, он преобразовал все значения с помощью float, но сгенерировал маску на основе строк (или их отсутствия):

In [147]: _.data
Out[147]: array([ 2., nan, nan, nan])

Я могу заменить оба типа «отсутствующих» определенным значением. Поскольку выполняется преобразование float, заливка должна быть 100 или '100':

In [151]: np.genfromtxt(txt,delimiter=',', missing_values='foo', 
    usecols=1, filling_values=100)
Out[151]: array([  2.,  nan, 100., 100.])

В более сложном случае я могу представить себе написание конвертера для столбца. Я только баловался этой функцией.

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

Подробнее в последующем вопросе: numpy genfromtxt - как обнаружить неверные входные значения int

person hpaulj    schedule 15.12.2020
comment
Благодарю. что вы посоветуете для не поплавков? Скажем, кто-то вставил строку, когда правильный формат - int? Прямо сейчас все чтение рухнет. Я надеялся вернуть массив масок с плохой записью, имеющей маску True. - person user3240688; 16.12.2020