2015-12-12 3 views
0

У меня есть серия текстовых файлов определенного формата. Например, file.txt выглядит следующим образом, с формой, как 50 столбцов букв и 70 строк текста:Каков стандартный способ проверки размеров ввода numpy?

AAAAAAAAAAAA 
BBBBBBBBBBBB 
CCCCCCCCCCCC 
DDDDDDDDDDDD 

Я хотел бы поместить следующее в Numpy массив, и делать манипуляции. Этот массив будет иметь определенные размеры. Форма представляет собой что-то вроде 50 столбцов букв, 70 строк текста, например. формы (70,50). Однако некоторые текстовые файлы являются «пропущенными буквами». Соответствующие файлы выглядят так:

AAAAAAAAAAAA 
BB BBBBBBBBB 
CCCCCCCCCCCC 
DDDDDD DDDDD 

Я бы хотел проверить, существуют ли какие-либо «пробелы» и выбросить ошибку. Существует ли стандартный метод с массивами numpy? Я делаю это до или после ввода текстов в массив?

Могу ли я сделать это с несколькими файлами? То есть, если я ввожу 200 файлов, конечные результаты представляют собой массив numpy, сформированный (200,70,50).

+0

Вы подумали о том, как читать эти данные в первую очередь? Пробелы могут вызвать проблему. –

+0

@ AndrasDeak Вот почему я спрашиваю. Если я просто загружу в массив, записи могут быть помещены в странные места. Однако, если я сначала сделаю какой-то алгоритм поиска для «пробелов», это может занять все время. – ShanZhengYang

+0

Есть ли причина, по которой вы не хотите читать во всем файле в виде строки: 'open (filename, 'r') как f: data = f.read()', а затем проверить, находится ли в этом пространстве пробел строка с '' 'в data'? – Reti43

ответ

2

Позволяет имитировать файл со списком строк текста:

In [401]: txt="""\ 
AAAAAAAAAAAA 
BB BBBBBBBBB 
CCCCCCCCCCCC 
DDDDDD DDDDD 
""" 

In [402]: txt=txt.splitlines() 

In [403]: txt 
Out[403]: ['AAAAAAAAAAAA', 'BB BBBBBBBBB', 'CCCCCCCCCCCC', 'DDDDDD DDDDD'] 

Как вы загрузке в массив? Часто мы используем loadtxt, но для столбцов данных

In [404]: np.loadtxt(txt,dtype=str) 
Out[404]: 
array(['AAAAAAAAAAAA', 'BB', 'CCCCCCCCCCCC', 'DDDDDD'], 
     dtype='|S12') 

Нет использования.

Давайте split на этих линиях

In [410]: [x.split() for x in txt] 
Out[410]: [['AAAAAAAAAAAA'], ['BB', 'BBBBBBBBB'], ['CCCCCCCCCCCC'], ['DDDDDD', 'DDDDD']] 

Линии с «белого пространства» превращаются в списки более чем на 1 срок

In [411]: [len(x.split())>1 for x in txt] 
Out[411]: [False, True, False, True] 

Так 2 строки имеют ошибки.

Я мог бы превратить txt в массив с одной буквой на столбе, передав строки через list(). Это дает np.array список, имеющих одинаковую длину.Пробел/пробел в конце строки может вызвать проблемы.

In [414]: A=np.array([list(x) for x in txt]) 

In [415]: A 
Out[415]: 
array([['A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A'], 
     ['B', 'B', ' ', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B'], 
     ['C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C'], 
     ['D', 'D', 'D', 'D', 'D', 'D', ' ', 'D', 'D', 'D', 'D', 'D']], 
     dtype='|S1') 

я мог проверить этот массив для ' ' персонажей что-то вроде:

In [418]: np.any(A==' ',axis=1) 
Out[418]: array([False, True, False, True], dtype=bool) 

Если линии имеют разную длину, то это array не будет 2d. Вместо этого он будет содержать 1d, содержащий списки.


Как было предложено в комментарии я мог бы сделать массив из целых строк, и использовать view к «разделяй» их в символы.

loadtxt с «нефункционирующих» разделителем бы создать 2d массив как:

In [434]: np.array([[x] for x in txt]) 
Out[434]: 
array([['AAAAAAAAAAAA'], 
     ['BB BBBBBBBBB'], 
     ['CCCCCCCCCCCC'], 
     ['DDDDDD DDDDD']], 
     dtype='|S12') 

И затем разделить его на персонажей:

In [435]: np.array([[x] for x in txt]).view('S1') 
Out[435]: 
array([['A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A'], 
     ['B', 'B', ' ', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B'], 
     ['C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C'], 
     ['D', 'D', 'D', 'D', 'D', 'D', ' ', 'D', 'D', 'D', 'D', 'D']], 
     dtype='|S1') 
+0

Аргумент delimiter для 'loadtxt' можно использовать, чтобы избежать разделения на пробелы. «view» может быть использован для просмотра массива в виде отдельных байтов. 'A = np.loadtxt ('text.txt', dtype = '| S12', delimiter = '\ n'). View ('| S1'). Reshape (-1, 12)' – Sammelsurium

1

Для большей части работы вам не нужен numpy. Приведенный ниже код считывает входной файл в список, каждый элемент будет линией входного файла (с завершением переноса новой строки). Затем он создает список одинаковой длины, каждый элемент сигнализирует, является ли данная строка пространственной. Если какой-либо из них - False, у вас возникнет проблема, и вы можете рассматривать этот случай по своему усмотрению. В противном случае записи без пробелов считываются в строковый тип numpy.ndarray.

import numpy as np 

#read data into list "lines" 
with open('input.inp') as f: 
    lines = [line.rstrip('\n') for line in f] 

#check ones with spaces 
nospaces = [not ' ' in line for line in lines] 

#throw an error here if you will 
if not all(nospaces): print 'Uh-oh!' 

#or just ignore the ones contaning a space and put the rest into an ndarray 
goodlines=np.array(lines)[np.array(nospaces)] #the only numpy-specific part 

Пример input.inp:

asfasf asfasfsa 
asffsafsafa 
asfafsafs afa 
faaffasaff 
fasafasffas 
afssfafs asafsas 

Выход:

In [1131]: run foo.py 
Uh-oh! 

In [1132]: lines 
Out[1132]: 
['asfasf asfasfsa', 
'asffsafsafa', 
'asfafsafs afa', 
'faaffasaff', 
'fasafasffas', 
'afssfafs asafsas'] 

In [1133]: goodlines 
Out[1133]: 
array(['asffsafsafa', 'faaffasaff', 'fasafasffas'], 
     dtype='|S16') 

Обратите внимание, что конечный результат имеет тип "строка 16 символов", так как мы впервые оказалось список в массив а затем выбросил ненужные части. С небольшой работой вы можете адаптировать это решение на свой вкус, и ваш пример также, по-видимому, предполагает, что ваши входные строки имеют одинаковую длину (в этом случае результирующий массив будет иметь оптимальный dtype).

+0

Не совсем конструктивный комментарий, но ... 'В [1131]'? В какой сессии вы работаете? – Reti43

+0

'run foo.py' в строке [1131] - это« система »(сортировка), используемая в' ipython'. Он запускает скрипт в основной рабочей области, оставляя переменные для проверки. Это может быть очень удобно, но смущает людей без опыта ipython. – hpaulj

+0

Я знаком с ipython, это номер, который был шоком для меня. – Reti43

1

Я предлагаю вам просто читать файл первым, проверьте пробелы, и если он пройдет тест, вы можете сохранить его для построения конечного массива. Бессмысленно манипулировать им дополнительными инструкциями в массив, если вы собираетесь отказаться от недопустимых данных или просто выбросить ошибку.

input_files = ['input0.txt', 'input1.txt', 'input2.txt'] 
valid_data = [] 

for i in input_files: 
    with open(i, 'r') as f: 
     data = f.read() 
     if ' ' not in data: 
      valid_data.append([list(s) for s in data.split('\n')]) 
     else: 
      print 'Invalid data in file {}. File will be ignored.'.format(i) 
result = np.array(valid_data) 

Код печатает предупреждение, когда встречается недопустимый файл. Если вы действительно хотите сбросить ошибку, это остановит весь процесс, и массив не будет создан. Чтобы сделать это, просто заменить печатное предупреждающее сообщение с

raise ValueError('Invalid data in file {}.'.format(i)) 

Пожалуйста, обратите внимание, что этот код предполагает, что все текстовые файлы имеют одинаковое число строк и столбцов. Если это может быть не так, уточните, как вы хотите, чтобы это было обработано.


Краткое объяснение того, как мы храним из строк в data списке.

Если у вас есть список списков и передать его в массив, он создаст 2D-массив этого списка списков. Например,

>>> data = [['A', 'A', 'A'], ['B', 'B', 'B']] 
>>> np.array(data) 
array([['A', 'A', 'A'], 
     ['B', 'B', 'B']], 
     dtype='|S1') 

Вот список имеет столько же пользователей, как наши строки в файле и подсписок содержит данные столбцов. Поэтому, если мы получим список списков списков, где у нас есть список каждого файла, когда мы передадим его в массив, у нас будут нужные размеры. В вашем примере для 200 файлов с 70 строк и 50 столбцов на файл мы получим (200, 70, 50).

Когда мы прочитаем содержимое файла за один раз, они будут в форме 'AAA\nBBB', поэтому как мы можем превратить это в [['A', 'A', 'A'], ['B', 'B', 'B']]?

>>> data = 'AAA\nBBB' 
>>> data.split('\n') 
['AAA', 'BBB'] 
>>> [list(s) for s in data.split('\n')] 
[['A', 'A', 'A'], ['B', 'B', 'B']] 
Смежные вопросы