2015-12-12 40 views
0

我有一系列特定格式的文本文件。例如,file.txt如下所示,用字母形状像50列,70行文字:检查numpy输入尺寸的标准方法是什么?

AAAAAAAAAAAA 
BBBBBBBBBBBB 
CCCCCCCCCCCC 
DDDDDDDDDDDD 

我想提出以下为numpy的阵列,并做操作。这个数组将有一定的尺寸。该形状类似于50列的字母,70行的文本,例如形状(70,50)。但是,一些文本文件是“丢失的字母”。有问题的文件看起来像这样

AAAAAAAAAAAA 
BB BBBBBBBBB 
CCCCCCCCCCCC 
DDDDDD DDDDD 

我想检查是否存在任何“空格”,并抛出一个错误。有没有一种标准的方法来处理numpy数组?在输入文本到数组之前或之后,我会这样做吗?

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

+0

你有没有想过如何读取这些数据呢?空间可能会导致问题已经存在。 –

+0

@AndrasDeak这正是我问的原因。如果我只是加载到数组中,则条目可能被放置在陌生的地方。但是,如果我首先对“空格”进行某种搜索算法,那可能会花费很长时间。 – ShanZhengYang

+0

是否有任何理由不希望以整个文件的形式读取字符串'open(filename,'r')作为f:data = f.read()',然后检查是否有空格数据中有'''的字符串? – Reti43

回答

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号线有错误。

我可以通过list()将字符串传递给每列有单个字母的数组txt。这给出了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') 
+0

'loadtxt'的分隔符参数可以用来避免在空格上分裂。然后可以使用'view'将数组视为单个字节。 ('| s1')。reshape(-1,12)'' – Sammelsurium

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)。

+0

不完全是建设性的评论,但是......在[1131]'?你正在运行什么类型的会话? – Reti43

+0

行[1131]中的'run foo.py'是'ipython'中使用的'系统'命令(各种)。它在主工作区运行脚本,留下变量供您检查。它可以非常方便,但是对于没有ipython经验的人来说很困惑。 – hpaulj

+0

我对ipython很熟悉,这是我感到震惊的数字。 – Reti43

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列表中存储字符串的简短说明。

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

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