2010-06-10 80 views
4

我有一个文本文件,其中包含行和列中的数据(总共约17000行)。每列的字符长度均匀,“未使用”字符由空格填充。例如,第一列的长度为11个字符,但该列中的最后四个字符总是空格(这样当用文本编辑器查看时,它看起来是一个很好的列)。有时如果条目少于7个字符,则有四个以上。使用python从文本文件导入数据

这些列不能用逗号,制表符或空格分隔。他们的字数也不尽相同(前两位是11位,后两位是8位,最后一位是5位 - 但也有一些是空格)。

我想要做的是在最后两列中导入条目(它是数字),如果第二列包含字符串'OW'的某处。任何帮助将不胜感激。

+0

你究竟是什么意思“上一个tw o列“?该行中的最后两个字符或最后两个空格分隔的条目? – 2010-06-10 08:02:36

+0

您的“行”是否被换行符分开? – tzaman 2010-06-10 08:38:52

+0

@Tim:如果第二列包含字符串'OW'...“,则OP写入”...最后两列...“,所以认为他有可能在句子内切换了含义:”最后两个字符,如果第二个字段包含字符串'OW'......考虑(重新)?读他的第2段:“列......也不是全部相同的字符数......最后一个是5”。 – 2010-06-10 09:16:41

回答

0
entries = ((float(line[30:38]), float(line[38:43])) for line in myfile if "OW" in line[11:22]) 

for num1, num2 in entries: 
    # whatever 
-2
entries = [] 
with open('my_file.txt', 'r') as f: 
    for line in f.read().splitlines() 
    line = line.split() 
    if line[1].find('OW') >= 0 
     entries.append((int(line[-2]) , int(line[-1]))) 

项是包含最后两个项目的元组

编辑数组:哎呀

+0

这是错误。line [1]'是行的第二个字符等。 – 2010-06-10 07:35:06

0

这里是一个函数,它可以帮助你:

def rows(f, columnSizes): 
    while True: 
     row = {} 
     for (key, size) in columnSizes: 
      value = f.read(size) 
      if len(value) < size: # EOF 
       return 
      row[key] = value 
     yield row 

为例它如何使用:

from StringIO import StringIO 

sample = StringIO("""aaabbbccc 
d e f 
g h i 
""") 

for row in rows(sample, [('first', 3), 
         ('second', 3), 
         ('third', 4)]): 
    print repr(row) 

请注意,与其他答案不同,此示例是而不是行分隔(它纯粹将文件用作字节提供程序,而不是行的迭代器),因为您特别提到这些字段未分隔,我认为行可能不是;具体考虑换行符。

您可以使用'in'运算符测试一个字符串是否是另一个字符串的子字符串。例如,

>>> 'OW' in 'hello' 
False 
>>> 'OW' in 'helOWlo' 
True 

因此,在这种情况下,你可能会做

if 'OW' in row['third']: 
    stuff() 

,但你可以明显地测试任何领域的任何价值,你认为合适。

3

在Python中,您可以使用切片在已知位置提取子字符串 - 通常使用列表[start:end]语法完成此操作。但是,您也可以创建可以稍后用于执行索引的切片对象。

所以,你可以做这样的事情:

columns = [slice(11,22), slice(30,38), slice(38,44)] 

myfile = open('some/file/path') 
for line in myfile: 
    fields = [line[column].strip() for column in columns] 
    if "OW" in fields[0]: 
     value1 = int(fields[1]) 
     value12 = int(fields[2]) 
     .... 

分离出片成一个列表可以很容易地改变,如果该数据格式发生变化的代码,或者你需要做的东西与其他领域。

+0

+1。很好的使用切片对象。Nit:在最后一个切片上有一个错误的错误。它应该是38, 44 – 2010-06-10 07:38:34

+0

@Matthew:感谢您的接触 - 修正了它 – 2010-06-10 07:45:27

4

Python的struct.unpack可能是拆分固定长度字段最快捷的方法。这里是一个将懒洋洋地阅读您的文件,并返回符合条件的号码的元组的函数:

import struct 

def parsefile(filename): 
    with open(filename) as myfile: 
     for line in myfile: 
      line = line.rstrip('\n') 
      fields = struct.unpack('11s11s8s8s5s', line) 
      if 'OW' in fields[1]: 
       yield (int(fields[3]), int(fields[4])) 

用法:

if __name__ == '__main__': 
    for field in parsefile('file.txt'): 
     print field 

测试数据:

1234567890a1234567890a123456781234567812345 
something maybe OW d 111111118888888855555 
aaaaa  bbbbb  1234 1212121233333 
other thinganother OW 121212 6666666644444 

输出:

(88888888, 55555) 
(66666666, 44444) 
+1

+1为概念,-1为注意细节为什么要剥离而不是rstrip?为什么在字符中加入'\ r'去掉?无论如何,根本没有提到线;也许行又名记录是固定长度的,没有分隔符,他有五个字段; unpack forma吨应该是''11s11s8s8s5s''和产量指数应该是3和4,而不是2和3. – 2010-06-10 08:04:14

+0

@约翰 - 是的,我注意到了我自己和固定的领域。切换到'rstrip'太好了。 '\ r \ n'只是为了在不同的行结束时保持健壮......可能只是'\ n'工作正常,但添加'\ r'并不会伤害imo。关于线条本身 - 他实际上提到了他的数据是“行列” - 听起来像是线条。 – tzaman 2010-06-10 08:08:27

+0

(1)如果文件以'r'或'rU'模式读取,行将以'\ n'结尾(可能最后一行可能不会被终止)。如果以'r'模式读取,在行结束符之前以'\ r''结尾是数据中的BUG;无声地剥离它并不“健壮”。在那里有'\ r''会让人们阅读你的代码时想知道为什么。 (2)固定长度的无分隔符记录通常与固定长度的字段紧密相关。 – 2010-06-10 08:34:55

相关问题