создание маскированного массива из текстовых полей - PullRequest
2 голосов
/ 11 сентября 2010

Документация numpy показывает пример маскирования существующих значений с помощью ma.masked a posteriori (после создания массива) или создания маскированного массива из списка того, что представляется допустимым типом данных (целое число, еслиdtype=int).Я пытаюсь прочитать данные из файла (и требует некоторых манипуляций с текстом), но в какой-то момент у меня будет список списков (или кортежей), содержащий строки, из которых я хочу создать числовой (плавающий) массив.

Примером данных может быть textdata='1\t2\t3\n4\t\t6' (типичный плоский текстовый формат после очистки).

Одна из моих проблем заключается в том, что пропущенные значения могут быть закодированы как '', что при попыткепреобразовать в число с плавающей точкой, используя аргумент dtype, скажет мне

ValueError: setting an array element with a sequence. 

Итак, я создал эту функцию

def makemaskedarray(X,missing='',fillvalue='-999.',dtype=float):
    arr = lambda x: x==missing and fillvalue or x    
    mask = lambda x: x==missing and 1 or 0
    triple = dict(zip(('data','mask','dtype'),
                      zip(*[(map(arr,x),map(mask,x)) for x in X])+
                      [dtype]))
    return ma.array(**triple)

, которая, кажется, выполняет свою задачу:

>>> makemaskedarray([('1','2','3'),('4','','6')])
masked_array(data =
 [[1.0 2.0 3.0]
 [4.0 -- 6.0]],
             mask =
 [[False False False]
 [False  True False]],
       fill_value = 1e+20)

Это способ сделать это?Или есть встроенная функция?

1 Ответ

1 голос
/ 12 сентября 2010

То, как вы это делаете, прекрасно. (хотя вы, безусловно, могли бы сделать его немного более читабельным, избегая создания временного "triple", просто разверните его на шаг позже, i.m.o.)

Встроенным способом является использование numpy.genfromtxt. В зависимости от объема предварительной обработки, который вам нужно сделать с вашим текстовым файлом, он может или не может делать то, что вам нужно. Тем не менее, в качестве основного примера: (Использование StringIO для имитации файла ...)

from StringIO import StringIO
import numpy as np

txt_data = """
1\t2\t3
4\t\t6
7t\8t\9"""

infile = StringIO(txt_data)
data = np.genfromtxt(infile, usemask=True, delimiter='\t')

Что дает:

masked_array(data =
 [[1.0 2.0 3.0]
 [4.0 -- 6.0]
 [7.0 8.0 9.0]],
             mask =
 [[False False False]
 [False  True False]
 [False False False]],
       fill_value = 1e+20)

Одно предостережение: если вы используете табуляции в качестве разделителя, а пустую строку - в качестве маркера пропущенного значения, у вас будут проблемы с пропущенными значениями в начале строки. (genfromtxt по сути звонит line.strip().split(delimiter)). Вам лучше использовать что-то вроде "xxx" в качестве маркера для пропущенных значений, если вы можете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...