读取一个.txt文件作为数组,并在Python中获取指定索引的值

时间:2018-12-25 22:42:55

标签: python csv numpy

我有一个很大的.txt数据文件,格式为(所有数​​字):

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

例如,我想将此矩阵的第二列导入变量。这是我编写的代码。首先,我将所有矩阵作为字符串导入到变量中,然后将其转换为数组,这里称为“数据”。然后,想要访问data [1] [1]或data [:] [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 :(得分:1)

经典方式如下:

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

print(array2d[:][0])

参考:List Comprehensions

我认为明智的numpy应该更快:/

  

更新

对于numpy,您可以使用loadtxt函数。

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

参考:Reading and Writing Data Files

  

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

答案 1 :(得分:0)

逐行读取文件并将每个文件保存在列表中等同于创建字符串列表:

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']

从中产生一个数组只会产生一维字符串数组。不能将其索引为二维数字数组:

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而言,一维形状(3,)一样好。

numpy具有良好的csv加载程序(实际上有两个):

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不是最快的加载器。如果您需要更高的速度,我们通常建议加载pandaspandas对引号和缺失值有一些更巧妙的处理,但是您似乎在这里不需要。 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数组,更接近原始数组列表。)