Чтение в форматированной строке для заполнения массива - PullRequest
1 голос
/ 05 июня 2019

Я пытаюсь прочитать определенное количество строк из TXT-файла в массив, используя Python. Текстовый файл отформатирован FORTRAN с 3 целыми числами, два из которых имеют длину 3 символа и один - длину 2 символа (то есть 24238 8. где значения 24,238, 8). В каждой строке 7 3 целых «группы». Ниже 8 строк текстового файла.

24238 8. 27237 8. 38 82 6. 38 96 6. 39 76 6. 39 77 6. 39 78 6.BARR  1
39 79 6. 39 80 6. 39 81 6. 39 82 6. 39 84 6. 39 85 6. 39 86 6.BARR  2
39 88 8. 39 89 8. 39 9010. 39 91 7. 39 92 7. 39 93 5. 39 96 6.BARR  3
39 9710. 39 9810. 39 9910. 3910010. 3910113. 3910212. 3910312.BARR  4
3910412. 3910512. 40 72 6. 40 73 6. 40 74 6. 40 75 6. 40 76 6.BARR  5
40 80 9. 40 8110. 40 8212. 40 8312. 40 84 8. 4010512. 4010612.BARR  6
40107 9. 40108 9. 40109 9. 41 70 6. 41 71 6. 41 77 6. 41 78 6.BARR  7
41 79 8. 41 80 8. 4110910. 41110 6. 41111 6. 41184 8. 42 73 2.BARR  8

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

import numpy as np
basin = open("il3_barrier","r")
zbm = np.full((171,251),-300)

Я хочу, чтобы 3-е значение в «группе» из трех заполнило массив на основе первого и второго значения. Например, я хочу, чтобы значение 8 занимало массив в расположении 24, 238 и так далее.

Я использую кусок кода из другого ответа на stackoverflow. Но я не уверен, как использовать циклы через строки.

def slices(s, *args):
    position = 0
    for length in args:
        yield s[position:position + length]
        position += length

Для этого примера с просмотром всего 8 строк я собирался попробовать что-то похожее на это:

for h in range(0,8): 
    tempLine = basin.readline()
    for k in range(0,7):
        inw,jnw,hw = list(slices(tempLine,3,3,2))
        inw = int(inw)
        jnw = int(jnw)
        zbm [inw,jnw] = hw

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

Ответы [ 3 ]

0 голосов
/ 05 июня 2019

Используя версию ширины поля delimiter Я могу загрузить первые две группы чисел, используя genfromtxt (txt - многострочная вставка образца файла):

In [221]: dels = [2,3,3, 3,3,3]; cols=[0,1,2,3,4,5]                                                    
In [222]: np.genfromtxt(txt.splitlines(), delimiter=dels, usecols=cols, dtype=float)                   
Out[222]: 
array([[ 24., 238.,   8.,  27., 237.,   8.],
       [ 39.,  79.,   6.,  39.,  80.,   6.],
       [ 39.,  88.,   8.,  39.,  89.,   8.],
       [ 39.,  97.,  10.,  39.,  98.,  10.],
       [ 39., 104.,  12.,  39., 105.,  12.],
       [ 40.,  80.,   9.,  40.,  81.,  10.],
       [ 40., 107.,   9.,  40., 108.,   9.],
       [ 41.,  79.,   8.,  41.,  80.,   8.]])

Мне пришлось использовать dtype float из-за '8'. поле. Я полагаю, я мог бы сократить поле и пропустить '.' вместо этого.

Или, если я укажу тип None, он создаст структурированный массив со смесью целочисленных и плавающих полей dtype.

In [223]: np.genfromtxt(txt.splitlines(), delimiter=dels, usecols=cols, dtype=None)                    
Out[223]: 
array([(24, 238,  8., 27, 237,  8.), (39,  79,  6., 39,  80,  6.),
       (39,  88,  8., 39,  89,  8.), (39,  97, 10., 39,  98, 10.),
       (39, 104, 12., 39, 105, 12.), (40,  80,  9., 40,  81, 10.),
       (40, 107,  9., 40, 108,  9.), (41,  79,  8., 41,  80,  8.)],
      dtype=[('f0', '<i8'), ('f1', '<i8'), ('f2', '<f8'), ('f3', '<i8'), ('f4', '<i8'), ('f5', '<f8')])

dels и cols могут быть расширены для обработки всех 7 групп.

Как только у вас появятся такие числа, их будет легко сопоставить с вашим окончательным массивом координат. Но я полагаю, у вас это уже получилось.

===

Разделение на '.' в свою собственную, неиспользуемую колонку:

In [226]: dels = [2,3,2,1, 3,3,2,1]; cols=[0,1,2, 4,5,6]                                               
In [227]: np.genfromtxt(txt.splitlines(), delimiter=dels, usecols=cols, dtype=int)                     
Out[227]: 
array([[ 24, 238,   8,  27, 237,   8],
       [ 39,  79,   6,  39,  80,   6],
       [ 39,  88,   8,  39,  89,   8],
       [ 39,  97,  10,  39,  98,  10],
       [ 39, 104,  12,  39, 105,  12],
       [ 40,  80,   9,  40,  81,  10],
       [ 40, 107,   9,  40, 108,   9],
       [ 41,  79,   8,  41,  80,   8]])
0 голосов
/ 07 июня 2019

Чтобы ответить на мой собственный вопрос:

def slices7(s,pos, *args):
    S=[]
    for length in args:
        S.append(s[pos:pos + length])
        pos += length
    return pos,S

Использовался с

for h in range(1,8):
    tempLine = basin.readline()
    pos=0
    for k in range(0,7):
        pos,AAA= list(slices7(tempLine,pos,3,3,3))
        try:
            inw = int(AAA[0])
            jnw = int(AAA[1])
            hw = float(AAA[2])
            zbm [inw,jnw] = hw
        except ValueError:
            pass
0 голосов
/ 05 июня 2019

Here You go = ^ .. ^ =

Краткие описания в коде.

import numpy as np

# load raw data
raw_data = []
with open('raw_data.txt', 'r') as file:
    data = file.readlines()
    for item in data:
        raw_data.append(item.strip())

# collect coordinates data
coordinates_data = []
for item in raw_data:
    for i in range(0, 63, 9):
        coordinates_data.append((item[0+i:2+i].strip(), item[2+i:5+i].strip(), item[6+i:7+i].strip().replace('.', '')))

# get values for array size
max_x = 0
max_y = 0
for item in coordinates_data:
    if max_x < int(item[0]):
        max_x = int(item[0])
    if max_y < int(item[1]):
        max_y = int(item[1])

# create empty array
final_array = np.zeros((max_x+1, max_y+1))

# load data into array
for item in coordinates_data:
    final_array[int(item[0]), int(item[1])] = int(item[2])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...