2010-06-10 82 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

相關問題