boundary
        layer 2
        datatype 0
        xy  15   525270 8663518   525400 8663518   525400 8664818   525660 8664818
                 525660 8663518   525790 8663518   525790 8664818   526050 8664818
                 526050 8663518   526180 8663518   526180 8665398   525980 8665598
                 525470 8665598   525270 8665398   525270 8663518
        endel

У меня есть координаты полигонов в этом формате, показанном выше. Каждый многоугольник начинается с «границы» и заканчивается «эндель». У меня возникли проблемы с извлечением номера слоя, количества точек и координат в массив numpy или фрейм данных pandas.

Чтобы быть конкретным для этого примера, мне нужен номер слоя (2), количество точек (15) и пары координат x-y.

with open('source1.txt', encoding="utf-8") as f:
    for line in f:
        line = f.readline()
        srs= line.split("\t")
        print(srs)

Это не разбивает числа, даже если они разделены табуляцией.

['        layer 255\n']
['        xy   5   0 0   22800000 0   22800000 22800000   0 22800000\n']
['        endel\n']

Это результат, который я получил с этим

with open('source1.txt', encoding="utf-8") as f:
    for line in f:
        line = f.readline()
        srs= line.split(" ")
        print(srs)

Это не то, что я хотел, но я тоже пробовал и все же получил плохой раскол

['', '', '', '', '', '', '', '', 'layer', '255\n']
['', '', '', '', '', '', '', '', 'xy', '', '', '5', '', '', '0', '0', '', '', '22800000', '0', '', '', '22800000', '22800000', '', '', '0', '22800000\n']
['', '', '', '', '', '', '', '', 'endel\n']

Я не мог перейти к numpy-части, так как я застрял в обработке строки из файла

Отредактировано по запросу

0
jax 6 Янв 2018 в 18:12

2 ответа

Лучший ответ

Вы можете использовать простой код, например:

res = []
coords = []
xy = False
with open('data.txt') as f:
    for line in f.readlines():
        if 'layer' in line:
            arr = line.split()
            layer = int(arr[-1].strip())
        elif 'xy' in line:
            arr = line.split()
            npoints = int(arr[1])
            coords = arr[2:]
            xy = True
        elif 'endel' in line:
            res.append([layer, npoints, coords[0:npoints]])
            xy = False
            coords = []
        elif xy:
            coords.extend(line.split())
print(res)

Затем вы можете преобразовать полученный список в массив numpy или что угодно, но обратите внимание, что в приведенном выше коде координаты по-прежнему являются строками.

1
Maciek 6 Янв 2018 в 15:57

Вы можете использовать регулярное выражение для разбора этого файла на блоки соответствующих данных, а затем для анализа каждого блока:

for block in re.findall(r'^boundary([\s\S]+?)endel', f.read()):
    m1=re.search(r'^\s*layer\s+(\d+)', block, re.M)
    m2=re.search(r'^\s*datatype\s+(\d+)', block, re.M)
    m3=re.search(r'^\s*xy\s+(\d+)\s+([\s\d]+)', block, re.M)
    if m1 and m2 and m3:
        layer=int(m1.group(1))
        datatype=int(m2.group(1))
        xy=int(m3.group(1))
        coordinates=[(int(x),int(y)) for x,y in zip(*[iter(m3.group(2).split())]*2)]
    else:
        print "can't parse {}".format(block)  

Переменное количество координат поддерживается после xy, и легко проверить, является ли количество проанализированных координат числом, ожидаемым с len(coordinates)==xy.

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

0
dawg 6 Янв 2018 в 18:13