检查numpy输入的尺寸的标准方法是什么?

时间:2015-12-12 23:17:46

标签: python arrays numpy text-files

我有一系列特定格式的文本文件。例如,file.txt如下所示,形状像50列字母和70行文字:

AAAAAAAAAAAA
BBBBBBBBBBBB
CCCCCCCCCCCC
DDDDDDDDDDDD

我想将以下内容放入numpy数组中,然后进行操作。该数组具有一定的尺寸。形状类似于50列字母,70行文本,例如形状(70,50)。但是,有些文本文件是"缺少字母"。有问题的文件看起来像这样

AAAAAAAAAAAA
BB BBBBBBBBB
CCCCCCCCCCCC
DDDDDD DDDDD

我想检查一下"空格"存在,并抛出一个错误。是否有与numpy数组有关的标准方法?我是在将文本输入数组之前或之后执行此操作吗?

我可以使用多个文件吗?也就是说,如果我输入200个文件,则最终结果是一个形状为(200,70,50)的numpy数组。

3 个答案:

答案 0 :(得分:2)

让我们用文本行列表模拟您的文件:

In [401]: txt="""\
AAAAAAAAAAAA
BB BBBBBBBBB
CCCCCCCCCCCC
DDDDDD DDDDD
"""

In [402]: txt=txt.splitlines()

In [403]: txt
Out[403]: ['AAAAAAAAAAAA', 'BB BBBBBBBBB', 'CCCCCCCCCCCC', 'DDDDDD DDDDD']

如何将其加载到数组中?我们经常使用loadtxt,但这适用于数据列

In [404]: np.loadtxt(txt,dtype=str)
Out[404]: 
array(['AAAAAAAAAAAA', 'BB', 'CCCCCCCCCCCC', 'DDDDDD'], 
      dtype='|S12')

没用。

让这些行split

In [410]: [x.split() for x in txt]
Out[410]: [['AAAAAAAAAAAA'], ['BB', 'BBBBBBBBB'], ['CCCCCCCCCCCC'], ['DDDDDD', 'DDDDD']]

带有'空格的行'变成超过1个词的列表

In [411]: [len(x.split())>1 for x in txt]
Out[411]: [False, True, False, True]

所以2行有错误。

通过将字符串传递给txt,我可以将list()转换为每列一个字母的数组。这为np.array提供了一个列表列表,长度相同。一行末尾的空格/空格可能会导致问题。

In [414]: A=np.array([list(x) for x in txt])

In [415]: A
Out[415]: 
array([['A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A'],
       ['B', 'B', ' ', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B'],
       ['C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C'],
       ['D', 'D', 'D', 'D', 'D', 'D', ' ', 'D', 'D', 'D', 'D', 'D']], 
      dtype='|S1')

我可以用' '个字符来测试这个数组:

In [418]: np.any(A==' ',axis=1)
Out[418]: array([False,  True, False,  True], dtype=bool)

如果行的长度不同,则此array不会是2d。它将改为包含列表的1d。

根据评论中的建议,我可以从整个字符串中创建一个数组,并使用view来划分'他们成了人物。

loadtxt'无效'分隔符将创建一个二维数组,如:

In [434]: np.array([[x] for x in txt])
Out[434]: 
array([['AAAAAAAAAAAA'],
       ['BB BBBBBBBBB'],
       ['CCCCCCCCCCCC'],
       ['DDDDDD DDDDD']], 
      dtype='|S12')

然后将其拆分为字符:

In [435]: np.array([[x] for x in txt]).view('S1')
Out[435]: 
array([['A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A'],
       ['B', 'B', ' ', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B'],
       ['C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C'],
       ['D', 'D', 'D', 'D', 'D', 'D', ' ', 'D', 'D', 'D', 'D', 'D']], 
      dtype='|S1')

答案 1 :(得分:1)

对于大部分工作,您不需要numpy。下面的代码将输入文件读入列表,每个元素将是输入文件的一行(删除尾随换行符)。然后它创建一个相同长度的列表,每个元素表示给定的字符串是否是无空格。如果其中任何一个是False,那么您就会遇到问题,并且可以根据需要处理此案例。否则,无空格条目将被读入字符串类型numpy.ndarray

import numpy as np

#read data into list "lines"
with open('input.inp') as f:
    lines = [line.rstrip('\n') for line in f]

#check ones with spaces
nospaces = [not ' ' in line for line in lines]

#throw an error here if you will
if not all(nospaces): print 'Uh-oh!'

#or just ignore the ones contaning a space and put the rest into an ndarray
goodlines=np.array(lines)[np.array(nospaces)] #the only numpy-specific part

示例input.inp

asfasf asfasfsa
asffsafsafa
asfafsafs afa
faaffasaff
fasafasffas
afssfafs asafsas

输出:

In [1131]: run foo.py
Uh-oh!

In [1132]: lines
Out[1132]: 
['asfasf asfasfsa',
 'asffsafsafa',
 'asfafsafs afa',
 'faaffasaff',
 'fasafasffas',
 'afssfafs asafsas']

In [1133]: goodlines
Out[1133]: 
array(['asffsafsafa', 'faaffasaff', 'fasafasffas'], 
      dtype='|S16')

请注意,最终输出的类型为“16个字符的字符串”,因为我们首先将列表转换为数组然后丢弃不必要的部分。通过小工作,您可以根据自己的喜好定制此解决方案,您的示例似乎也建议您的输入行具有相同的长度(在这种情况下,生成的数组将具有最佳dtype)。

答案 2 :(得分:1)

我建议您先阅读文件,检查空格,如果通过测试,您可以将其存储为最终的数组构造。如果您要丢弃无效数据,或者直接抛出错误,则使用附加指令操作数组是没有意义的。

input_files = ['input0.txt', 'input1.txt', 'input2.txt']
valid_data = []

for i in input_files:
    with open(i, 'r') as f:
        data = f.read()
        if ' ' not in data:
            valid_data.append([list(s) for s in data.split('\n')])
        else:
            print 'Invalid data in file {}. File will be ignored.'.format(i)
result = np.array(valid_data)

遇到无效文件时,代码会输出警告。如果你真的想抛出一个错误,它将停止整个过程,不会构造任何数组。为此,只需用

替换打印的警告消息即可
raise ValueError('Invalid data in file {}.'.format(i))

请注意,此代码假定所有文本文件具有相同的行数和列数。如果情况可能并非如此,请说明您希望如何处理此事。

关于我们如何在data列表中存储字符串的简短说明。

如果您有一个列表列表并将其传递给数组,它将创建该列表列表的2D数组。例如,

>>> data = [['A', 'A', 'A'], ['B', 'B', 'B']]
>>> np.array(data)
array([['A', 'A', 'A'],
       ['B', 'B', 'B']], 
      dtype='|S1')

这里,列表包含与文件中的行一样多的成员,子列表包含列数据。因此,如果我们得到一个列表列表,我们有一个每个文件的列表,当我们将它传递给数组时,我们将得到所需的维度。在您的示例中,对于每个文件包含70行和50列的200个文件,我们将获得(200,70,50)。

当我们一次性阅读文件的内容时,它们将采用'AAA\nBBB'格式,那么我们如何将其转换为[['A', 'A', 'A'], ['B', 'B', 'B']]

>>> data = 'AAA\nBBB'
>>> data.split('\n')
['AAA', 'BBB']
>>> [list(s) for s in data.split('\n')]
[['A', 'A', 'A'], ['B', 'B', 'B']]