检索在单个键下具有多个值的字典中的最高值

时间:2012-02-15 23:00:11

标签: python dictionary

我对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

这最终只是打印每个键,而不是只有最大百分比的键。有什么想法吗?谢谢!

4 个答案:

答案 0 :(得分:2)

您可以使用csv来解析制表符描述的数据文件,(尽管您发布的数据看起来是列间距数据!?)

由于数据文件中的第一行提供了字段名称,因此DictReader很方便,因此您可以通过人类可读的名称来引用这些列。

csv.DictReader返回一个可迭代的行(dicts)。如果您使用max列作为Percent Match获取可迭代的key,则可以找到匹配率最高的行:

将此(制表符分隔)数据用作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'}}

答案 1 :(得分: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 :(得分: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]))

我在一个文件上作证如下:

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

答案 3 :(得分: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))