Чтение файла .txt в виде массива и получение значения указанного индекса в Python - PullRequest
0 голосов
/ 26 декабря 2018

У меня большой файл данных .txt в формате (все числа):

0 1.2 2 3.1
20 21.2 22 23
30 31 32 33.01

Я хочу импортировать, например, 2-й столбец этой матрицы в переменную.Вот код, который я написал.Сначала я импортирую всю матрицу в переменную в виде строки и преобразую ее в массив с именем «data».Затем вы хотите получить доступ к данным [1] [1] или данным [:] [1], но выдает следующую ошибку

IndexError: слишком много индексов для массива

Есть идеи, в чем заключается ошибка или как эффективно выполнять работу?Большое спасибо

import csv
data=[]
with open('test.txt', 'r') as f:
  reader = csv.reader(f, delimiter=' ', skipinitialspace=True)
   for line in f:
      if line.endswith('\n'):
          line=line[:-1] 

      data=np.asarray(line)  
      print(data)

Ответы [ 2 ]

0 голосов
/ 26 декабря 2018

Чтение файла построчно и сохранение каждого в списке равносильно созданию списка строк:

In [98]: txt='''0 1.2 2 3.1
    ...: 20 21.2 22 23
    ...: 30 31 32 33.01'''.splitlines()
In [99]: txt
Out[99]: ['0 1.2 2 3.1', '20 21.2 22 23', '30 31 32 33.01']

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

In [100]: np.array(txt)
Out[100]: array(['0 1.2 2 3.1', '20 21.2 22 23', '30 31 32 33.01'], dtype='<U14')

Если вы сначала разбиваете строки на подстроки:

In [101]: [line.split() for line in txt]
Out[101]: 
[['0', '1.2', '2', '3.1'],
 ['20', '21.2', '22', '23'],
 ['30', '31', '32', '33.01']]
In [102]: np.array([line.split() for line in txt], dtype=float)
Out[102]: 
array([[ 0.  ,  1.2 ,  2.  ,  3.1 ],
       [20.  , 21.2 , 22.  , 23.  ],
       [30.  , 31.  , 32.  , 33.01]])

Это двумерный массив.

Мы можем выбрать столбец из этого массива.Но обратите внимание, что результатом является массив 1d:

In [104]: np.array([line.split() for line in txt], dtype=float)[:,1]
Out[104]: array([ 1.2, 21.2, 31. ])

Не беспокойтесь о том, что это «строка» или «столбец».Мы могли бы изменить форму на (1,3) или (3,1), но для большинства numpy целей 1d форма (3,) также хороша.

numpy имеет хорошее csv loader (на самом деле два):

In [105]: np.genfromtxt(txt)
Out[105]: 
array([[ 0.  ,  1.2 ,  2.  ,  3.1 ],
       [20.  , 21.2 , 22.  , 23.  ],
       [30.  , 31.  , 32.  , 33.01]])

Обычно genfromtxt присваивается имя файла, но он прекрасно работает с любыми строками, такими как список txt.

И если вас интересует только один столбец, вы можете указать его с помощью usecols (есть много других возможных параметров):

In [106]: np.genfromtxt(txt, usecols=1)
Out[106]: array([ 1.2, 21.2, 31. ])

genfromtxt не самый быстрый загрузчик.Если вам нужна большая скорость, мы обычно рекомендуем загруженный pandas.pandas имеет более изящную обработку кавычек и пропущенных значений, но вам здесь это не нужно.numpy пользователи, кажется, не очень часто используют модуль csv;может быть, это просто не нужно.


Если вам действительно нужен column vector, вот как использовать reshape:

In [110]: col1 = np.genfromtxt(txt, usecols=1)
In [111]: col1
Out[111]: array([ 1.2, 21.2, 31. ])
In [112]: col1.reshape(3,1)
Out[112]: 
array([[ 1.2],
       [21.2],
       [31. ]])

Давайтепостройте массив строка за строкой:

In [116]: data = []
In [117]: for line in txt:
     ...:     arr = np.array(line.split(), dtype=float)
     ...:     print(arr.shape)
     ...:     data.append(arr)
     ...:     print(data)
     ...:     
     ...:     
(4,)
[array([0. , 1.2, 2. , 3.1])]
(4,)
[array([0. , 1.2, 2. , 3.1]), array([20. , 21.2, 22. , 23. ])]
(4,)
[array([0. , 1.2, 2. , 3.1]), array([20. , 21.2, 22. , 23. ]), array([30.  , 31.  , 32.  , 33.01])]

data теперь является списком массивов:

In [118]: data
Out[118]: 
[array([0. , 1.2, 2. , 3.1]),
 array([20. , 21.2, 22. , 23. ]),
 array([30.  , 31.  , 32.  , 33.01])]

Объедините эти массивы в один массив:

In [119]: np.array(data)
Out[119]: 
array([[ 0.  ,  1.2 ,  2.  ,  3.1 ],
       [20.  , 21.2 , 22.  , 23.  ],
       [30.  , 31.  , 32.  , 33.01]])

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

0 голосов
/ 26 декабря 2018

Классический способ будет выглядеть следующим образом:

with open('test.txt') as txt:
    array2d = [[float(digit) for digit in line.split()] for line in txt]

print(array2d[:][0])

Ссылка: Список понятий

Я думаю, что производительность мудрый numpy должен быть быстрее: /

Обновление:

Для numpy вы можете использовать функцию loadtxt.

import numpy as np
textfile = np.loadtxt("test.txt")
print(textfile[0][0])

Ссылка: Чтение и запись файлов данных

Update2: IndexError: слишком много индексов для массива

import csv 
import numpy as np #missing
data = [] #create a empty array
with open('test.txt', 'r') as f: #opens the textfile in readmode and stores in f
    reader = csv.reader(f, delimiter=' ', skipinitialspace=True) #creating a reader instance but never used
    for line in f: #loop for each line in file
            if line.endswith('\n'): #if the file ends with a new line
                line = line[:-1] #set to last line

            data = np.asarray(line) # here is one bigger mistake you overwrite the data array with just one line
            print(data) #print out this one line

Таким образом, вы получите только последнюю строку, сохраненную в ваших данныхмассив.

Примечание: Нет способа определить длину строки, поэтому вы должны прочитать в файле.Вы не можете перейти к этой конкретной строке, есть несколько способов улучшить производительность, поэтому, пожалуйста, сообщите нам, насколько велик ваш файл или какова ожидаемая скорость.

Update3: Получить столбец

import numpy as np
textfile = np.loadtxt("test.txt")
print(textfile[:,0])

Ссылка: Numpy Indexing

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