2012-02-15 40 views
1

我對Python有點新,我有一個問題。 我有一個文件,每個唯一標識符有5個結果。每個結果都有一個百分比匹配以及其他各種數據。我的目標是找到匹配率最高的結果,然後從原始行中檢索更多信息。 例如檢索單個鍵下具有多個值的字典中的頂部值

Name Organism Percent Match  Misc info 
1  Human  100    xxx  
1  Goat   95    yyy 
1  Pig   90    zzz 

我試圖通過把每個鍵在字典的值是(爲每個鍵即多個值),每百分數比賽唯一給定的名稱來解決這個問題。我認爲繼續進行的唯一方法是將此字典中的值轉換爲列表,然後對列表進行排序。然後,我想要檢索列表中最大的值(列表[0]或列表[-1]),然後從原始行中檢索更多信息。 這裏是我的代碼迄今

list = [] 
if "1" in line: 
    id = line 
    bsp = id.split("\t") 
    uid = bsp[0] 
    per = bsp[2] 

    if not dict.has_key(uid): 
     dict[uid] = [] 
    dict[uid].append(per) 
    list = dict[uid] 
    list.sort() 
if list[0] in dict: 
    print key 

這最終只是打印每一個關鍵,而不是隻具有最大百分比。有什麼想法嗎?謝謝!

+0

注意:上面的示例文件,每個「1」是該項目的名稱,並且100,95和90是百分比匹配等。 – Vince 2012-02-15 23:01:03

+1

>。<不使用列表作爲一個變量名或者dict。 – 2012-02-15 23:04:38

+0

你是否在循環中執行給定的代碼?在這種情況下,它會在讀取整個文件之前打印密鑰。而且,在排序列表後,'my_list [0]'將是最小的項目,而不是最大的項目。 – 2012-02-15 23:07:38

回答

1

你應該能夠做這樣的事情:

lines = [] 
with open('data.txt') as file: 
    for line in file: 
     if line.startswith('1'): 
      lines.append(line.split()) 

best_match = max(lines, key=lambda k: int(k[2])) 

讀取文件後lines會是這個樣子:

>>> pprint.pprint(lines) 
[['1', 'Human', '100', 'xxx'], 
['1', 'Goat', '95', 'yyy'], 
['1', 'Pig', '90', 'zzz']] 

然後你想從lines,其中入境第三項的值爲int最高,可以這樣表示:

>>> max(lines, key=lambda k: int(k[2])) 
['1', 'Human', '100', 'xxx'] 

所以在這個best_match年底將與您感興趣的線路上的數據列表

或者,如果你想獲得真正棘手,你可以得到的線在一個(複雜)的步驟:

with open('data.txt') as file: 
    best_match = max((s.split() for s in file if s.startswith('1')), 
        key=lambda k: int(k[2])) 
2

你可以使用csv解析製表符分隔的數據文件,(雖然數據您發佈看起來是列隔開的數據!?)

由於在數據文件中的第一行給出場名稱,一個DictReader很方便,所以你可以參考這些列通過人類可讀的名字。

csv.DictReader返回可迭代的行(字符串)。如果您在使用Percent Match列作爲key採取迭代的max,你可以找到最高的匹配百分比該行:

使用這個(製表符分隔)的數據爲test.dat

Name Organism Percent Match Misc info 
1 Human 100 xxx 
1 Goat 95 yyy 
1 Pig 90 zzz 
2 Mouse 95 yyy 
2 Moose 90 zzz 
2 Manatee 100 xxx 

的程序

import csv 

maxrows = {} 
with open('test.dat', 'rb') as f: 
    for row in csv.DictReader(f, delimiter = '\t'): 
     name = row['Name'] 
     percent = int(row['Percent Match']) 
     if int(maxrows.get(name,row)['Percent Match']) <= percent: 
      maxrows[name] = row 

print(maxrows) 

產生

{'1': {'info': None, 'Percent Match': '100', 'Misc': 'xxx', 'Organism': 'Human', 'Name': '1'}, '2': {'info': None, 'Percent Match': '100', 'Misc': 'xxx', 'Organism': 'Manatee', 'Name': '2'}} 
+0

非常有趣,謝謝!但是,我認爲主要是由於我的輸入文件示例中有一個錯誤,如果有多個輸入,此腳本只打印最大行而不打印最大行。這是我沒有指定的錯誤。感謝您向我展示導入csv! – Vince 2012-02-17 01:36:32

+0

好的,我改變了一下,爲每個名字收集一個最大行。 – unutbu 2012-02-17 02:15:00

0
with open('datafile.txt', 'r') as f: 
    lines = file.read().split('\n') 

matchDict = {} 

for line in lines: 
    if line[0] == '1': 
     uid, organism, percent, misc = line.split('\t') 
     matchDict[int(percent)] = (organism, uid, misc) 

highestMatch = max(matchDict.keys()) 

print('{0} is the highest match at {1} percent'.format(matchDict[highestMatch][0], highestMatch)) 
1

我想你可能會尋找類似:

from collections import defaultdict 

results = defaultdict(list) 
with open('data.txt') as f: 
    #next(f)  # you may need this so skip the header 
    for line in f: 
     splitted = line.split() 
     results[splitted[0]].append(splitted[1:]) 

maxs = {} 
for uid,data in results.items(): 
    maxs[uid] = max(data, key=lambda k: int(k[1])) 

我已經testif像一個文件:

Name Organism Percent Match  Misc info 
1  Human  100    xxx  
1  Goat   95    yyy 
1  Pig   90    zzz 
2  Pig   85    zzz 
2  Goat   70    yyy 

,結果是:

{'1': ['Human', '100', 'xxx'], '2': ['Pig', '85', 'zzz']} 
+1

+1擊敗我。 – retracile 2012-02-15 23:17:49

+0

謝謝!這個網站的岩石。 – Vince 2012-02-17 01:28:13

+0

@Vince:不客氣!不要忘記回饋社區投票選出最佳答案和[接受](http://meta.stackexchange.com/q/5234/177799)最有用的答案:) – 2012-02-17 09:56:42

相關問題