Страницы

Поиск по вопросам

понедельник, 9 декабря 2019 г.

Разбиение строк в формате с фиксированной шириной полей и необязательными значениями

#python #python_3x #регулярные_выражения #строки #python_2x


Есть большой массив данных. 

Пример строки из массива: 

20046 2005  27.0  44.3   9.0  15.9   3.6   9.2   9.2  37.5  18.3  18.6  24.4  26.0


Где первые два значения - номер метеостанции и год, остальные - температуры воздуха,
начиная с января. Значения разделяются пробелами, при этом количество пробелов варьируется
от 1 до 3. Значения температур, которые не были зафиксированы метеостанцией заменяется
пробелами, т.е. в массиве допускается строка вида: 

20667 2014   5.5   2.4   7.9   8.1              42.7              10.1            


Необходима регулярка, которая бы разбивала эту строку на массив вида:

['20667','2014','5.5','2.4','7.9','8.1','','','42.7','','','10.1','','']

    


Ответы

Ответ 1



По описанию ваших входных данных, похоже что это fixed-width файл. В этом случае будет очень удобно воспользоваться Pandas модулем: import pandas as pd cols = ['id', 'year'] + ['m{}'.format(i) for i in range(1, 13)] df = pd.read_fwf(r'D:\temp\.data\655212.txt', header=None, names=cols) print(df) Результат: In [136]: df Out[136]: id year m1 m2 m3 m4 m5 m6 m7 m8 m9 m10 m11 m12 0 20046 2005 27.0 44.3 9.0 15.9 3.6 9.2 9.2 37.5 18.3 18.6 24.4 26.0 1 20047 2005 26.5 NaN 7.5 17.3 NaN NaN 10.2 39.9 19.7 NaN 20.4 20.0 Также можно воспользоваться идеей от @jfs для того чтобы назвать столбцы по именам месяцев: import calendar cols = ['id', 'year'] + list(calendar.month_abbr)[1:] df = pd.read_fwf(r'D:\temp\.data\655212.txt', header=None, names=cols) Результат: In [139]: df Out[139]: id year Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec 0 20046 2005 27.0 44.3 9.0 15.9 3.6 9.2 9.2 37.5 18.3 18.6 24.4 26.0 1 20047 2005 26.5 NaN 7.5 17.3 NaN NaN 10.2 39.9 19.7 NaN 20.4 20.0 Исходный файл: 20046 2005 27.0 44.3 9.0 15.9 3.6 9.2 9.2 37.5 18.3 18.6 24.4 26.0 20047 2005 26.5 7.5 17.3 10.2 39.9 19.7 20.4 20.0

Ответ 2



Предполагая, что под каждую температуру месяца отводится ровно 6 позиций (фиксированная ширина полей), можно распознать данные со стандартного ввода или из файлов, заданных в командной строчке, используя fileinput стандартный модуль: #!/usr/bin/env python import fileinput width = 6 for line in fileinput.input(): station_id, year, s = line.split(None, 2) s = s.rstrip('\n').rjust(12 * width) # pad with leading space temps = [s[i:i+width].strip() for i in range(0, len(s), width)] print(temps) Пример $ python parse-fixed-width-temps.py input.txt ['27.0', '44.3', '9.0', '15.9', '3.6', '9.2', '9.2', '37.5', '18.3', '18.6', '24.4', '26.0'] ['5.5', '2.4', '7.9', '8.1', '', '', '42.7', '', '', '10.1', '', '']

Ответ 3



Если предположить, что каждая строка имеет фиксированную длину (82 символа), и под каждый месяц в строке отведено 5 символов (XX.XX), получаем, что разделителем должны быть два пробельных символа. Значит, можно заменить лишние пробелы на отсутствующее значение + пробелы-разделители, и попробовать поделить строку следующим образом: data = '20667 2014 5.5 2.4 7.9 8.1 42.7 10.1 ' print [val.strip() for val in data.replace(' ', ' n/d ').split(' ')] >>> ['20667 2014', '5.5', '2.4', '7.9', '8.1', 'n/d', 'n/d', '42.7', 'n/d', 'n/d', '10.1', 'n/d', 'n/d']

Комментариев нет:

Отправить комментарий