Python - чтение текстового файла данных с разными разделителями - PullRequest
0 голосов
/ 05 июля 2018

У меня есть файл, в котором поля разделены символом ':', подполя разделены символом ';', а элементы внутри подполей разделены символом ','.

Я хотел бы прочитать это Python. Через некоторое время я, вероятно, мог бы прочитать это построчно, а затем разделить все, но я считаю, что что-то уже существует для такого рода вещей?

Строка файла:

   0 :   16,  250 :  1 :  0.053 :RIG : DIS :  1 :   48, 220;  2 :   42, 241;  2 :   43, 251;  3 :   25, 266;  1 :   36, 287;  2 

Я действительно пытался:

Dat = np.genfromtxt(path, delimiter= ':', dtype = None, skip_header = 4,  skip_footer = 5, encoding = None)

По причине, которую я не понимаю, она возвращает мне только первый столбец файла. Тем не менее, это работает, если я изменяю на delimiter= ','.

Это дает мне 7 полей, которые я действительно могу разделить.

Тогда: 1) Как бы вы сделали, чтобы прочитать этот файл? 2) Используя np.genfromtxt, почему я получаю только первый столбец, используя ':' в качестве разделителя?

Ответы [ 2 ]

0 голосов
/ 05 июля 2018
In [280]: txt=['   0 :   16,  250 :  1 :  0.053 :RIG : DIS :  1 :   48, 220;  2 
     ...: :   42, 241;  2 :   43, 251;  3 :   25, 266;  1 :   36, 287;  2 '
     ...: ]

In [282]: np.genfromtxt(txt,delimiter=':',dtype=None, encoding=None)
Out[282]: 
array((0, '   16,  250 ', 1, 0.053, 'RIG ', ' DIS ', 1, '   48, 220;  2 ', '   42, 241;  2 ', '   43, 251;  3 ', '   25, 266;  1 ', '   36, 287;  2'),
      dtype=[('f0', '<i8'), ('f1', '<U12'), ('f2', '<i8'), ('f3', '<f8'), ('f4', '<U4'), ('f5', '<U5'), ('f6', '<i8'), ('f7', '<U15'), ('f8', '<U15'), ('f9', '<U15'), ('f10', '<U15'), ('f11', '<U14')])

Это структурированный массив с 11 полями, представляющий собой целое число, строку и число с плавающей точкой Это потому, что dtype=None говорит ему выводить тип d для каждого столбца.

Разделение на , создает массив из 7 столбцов (здесь 1d, потому что есть только одна строка ввода, но это будет 2d с большим количеством):

In [283]: np.genfromtxt(txt,delimiter=',',dtype=None, encoding=None)
Out[283]: 
array(['0 :   16', '  250 :  1 :  0.053 :RIG : DIS :  1 :   48',
       ' 220;  2 :   42', ' 241;  2 :   43', ' 251;  3 :   25',
       ' 266;  1 :   36', ' 287;  2'], dtype='<U42')

Но обратите внимание, это все строки.

genfromtxt не принимает несколько разделителей, но принимает входные данные от всего, что передает ему строки.

Так что, если я определю функцию, которая заменяет разделители:

In [285]: def foo(astr):
     ...:     return astr.replace(':',',').replace(';',',')
     ...: 
     ...: 
In [286]: np.genfromtxt([foo(a) for a in txt],delimiter=',',dtype=None, encoding
     ...: =None)
Out[286]: 
array((0, 16, 250, 1, 0.053, 'RIG ', ' DIS ', 1, 48, 220, 2, 42, 241, 2, 43, 251, 3, 25, 266, 1, 36, 287, 2),
      dtype=[('f0', '<i8'), ('f1', '<i8'), ('f2', '<i8'), ('f3', '<i8'), ('f4', '<f8'), ('f5', '<U4'), ('f6', '<U5'), ('f7', '<i8'), ('f8', '<i8'), ('f9', '<i8'), ('f10', '<i8'), ('f11', '<i8'), ('f12', '<i8'), ('f13', '<i8'), ('f14', '<i8'), ('f15', '<i8'), ('f16', '<i8'), ('f17', '<i8'), ('f18', '<i8'), ('f19', '<i8'), ('f20', '<i8'), ('f21', '<i8'), ('f22', '<i8')])

Теперь я разбил входные данные на структурированный массив с 23 полями, снова смесью целых чисел, чисел с плавающей запятой и (меньших) строк.

genfromtxt позволяет мне определить dtype, который мог бы группировать подполя вместе.

Например, просто пытаюсь обработать первые 6 столбцов:

In [298]: dt = np.dtype([('f0','i'),('f1','i',2),('f2','i'),('f3','i'),('f4','U3
     ...: ')])
In [299]: np.genfromtxt([foo(a) for a in txt],delimiter=',',dtype=dt, encoding=N
     ...: one,usecols=range(6))
Out[299]: 
array((0, [ 16, 250], 1, 0, 'RIG'),
      dtype=[('f0', '<i4'), ('f1', '<i4', (2,)), ('f2', '<i4'), ('f3', '<i4'), ('f4', '<U3')])

Я сгруппировал '16,250' в одно поле, содержащее 2 целых. Позже 48,220; 2,42,241; 2 'может вложить 3 поля (определенных с помощью'; '), и в пределах этих 2,2 и 1 подполей.

genfromtxt допускает другую форму разделителя - фиксированную ширину поля.


Speedwise, genfromtxt не предлагает никаких улучшений по сравнению с вашим собственным. Он по-прежнему должен читать каждую строку, разбивать ее и собирать значения в список списков. В конце он преобразует это в массив.

pandas имеет более быстрое csv устройство чтения, но этот случай может быть слишком сложным, чтобы использовать его. Параметр engine=python заставляет его использовать более медленную версию Python.

0 голосов
/ 05 июля 2018

Решение с использованием панд:

data = pd.read_csv('data.txt',
                   sep=";|:|,",
                   header=None,
                   engine='python')

Это запишет каждое значение в новый столбец. Надеюсь, это может быть полезно.

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