匹配列表中的索引 - 字典 - Python

4

我有一个包含列表的字典:

d = [('Locus_1',
  [['>Safr02', 'R', '104'],
   ['>Safr03', 'G', '104'],
   ['>Safr04', 'A', '104'],
   ['>Safr10', 'A', '104'],
   ['>Safr02', 'K', '110'],
   ['>Safr03', 'T', '110'],
   ['>Safr04', 'T', '110'],
   ['>Safr10', 'T', '110']]),
 ('Locus_2',
  [['>Safr01', 'C', '15'],
   ['>Safr02', 'Y', '15'],
   ['>Safr04', 'Y', '15'],
   ['>Safr07', 'Y', '15'],
   ['>Safr01', 'Y', '78'],
   ['>Safr02', 'T', '78'],
   ['>Safr04', 'T', '78'],
   ['>Safr07', 'T', '78']])]

以下代码创建了字典:

snp_file = open(sys.argv[2], 'r')
snps = csv.reader(snp_file, delimiter=',')

d = OrderedDict()

for row in snps:
    key = row[0]
    d.setdefault(key,[])
    d[key].append(row[1:])

数据可以在这里找到:https://www.dropbox.com/sh/3j4i04s2rg6b63h/AADkWG3OcsutTiSsyTl8L2Vda?dl=0 我有一个(对我来说)比较复杂的任务要处理这些数据,我想将其分成几个步骤,但我不确定如何做到这一点:
我需要根据Locus_X名称成对查看数据(我有另一个文件中的一对列表,但为了本问题,我们只说Locus_1和Locus_2是一对)。
因此,对于Locus_1:Locus_2这对,我需要匹配每个Locus列表(SafrXX)内位置0处的名称。对于相等的名称(例如Locus_1:Safr02-Locus_2:Safr02),我需要比较位置1处的字母,所以对于这个例子,字母将是:R:Y。
更加棘手的是,我需要针对位置2的所有组合进行这样的操作。
因此,在上面的示例中,我需要比较的字母是:
R:Y
R:T
K:Y
K:T

现在,我并不要求你编写一段真正能够实现此功能的代码,而只是想问一下,最合理的划分和处理此任务的方式是什么?是否有什么我可以先做的事情,以便不必在一个复杂的多重嵌套循环中完成所有操作?


1
你能否发布一行输出应该是什么样子的?从你的数据来看,除了第一个字段外,行之间没有明显的依赖关系。 - Oliver Friedrich
2个回答

0

我认为这里描述的问题不够清晰。或者更好的说法是,你提供的数据依赖关系可以解释你需要的输出结果。

我尝试了一下你的代码,起初我以为只需使用Python的zip函数就能轻松解决:

import csv
from collections import OrderedDict

snp_file = open('data.txt', 'r')
snps = csv.reader(snp_file, delimiter=',')
d = OrderedDict()
for row in snps:
    key = row[0]
    d.setdefault(key,[])
    d[key].append(row[1:])

for left,right in zip(d['Locus_1'],d['Locus_2']):
    print(left,right)

这给了我以下输出,但它对您也没有帮助,因为第一列未排序且不匹配:

['>Safr02', 'R', '104'] ['>Safr01', 'C', '15']
['>Safr03', 'G', '104'] ['>Safr02', 'Y', '15']
['>Safr04', 'A', '104'] ['>Safr04', 'Y', '15']
['>Safr10', 'A', '104'] ['>Safr07', 'Y', '15']
['>Safr02', 'K', '110'] ['>Safr01', 'Y', '78']
['>Safr03', 'T', '110'] ['>Safr02', 'Y', '78']
['>Safr04', 'T', '110'] ['>Safr04', 'T', '78']
['>Safr10', 'T', '110'] ['>Safr07', 'T', '78']

像这样将排序添加到脚本中也没有帮助,因为列表的长度相等,但是数据中的第一个键不匹配:

loc1 = sorted(d['Locus_1'], key=lambda lst: lst[0]): 
loc2 = sorted(d['Locus_2'], key=lambda lst: lst[0]): 

for left,right in zip(loc1,loc2):
    print(left,right)

这将以下内容输出到屏幕:

['>Safr02', 'R', '104'] ['>Safr01', 'C', '15']
['>Safr02', 'K', '110'] ['>Safr01', 'Y', '78']
['>Safr03', 'G', '104'] ['>Safr02', 'Y', '15']
['>Safr03', 'T', '110'] ['>Safr02', 'Y', '78']
['>Safr04', 'A', '104'] ['>Safr04', 'Y', '15']
['>Safr04', 'T', '110'] ['>Safr04', 'T', '78']
['>Safr10', 'A', '104'] ['>Safr07', 'Y', '15']
['>Safr10', 'T', '110'] ['>Safr07', 'T', '78']

所以我转而使用嵌套循环,看看能否更好地掌握您的数据处理方式:

for l1 in loc1:
    for l2 in loc2:
        if l1[0] == l2[0]:
            print('{}-{}({}):{}({})'.format(l1[0],l1[1],l1[2],l2[1],l2[2]))

但这也没有给我任何线索,你自己看(输出很简短,因为我仍然没有掌握要点):

>Safr02-R(104):Y(15)
>Safr02-R(104):Y(78)
>Safr02-K(110):Y(15)
>Safr02-K(110):Y(78)
>Safr04-A(104):Y(15)
>Safr04-A(104):T(78)
>Safr04-T(110):Y(15)
>Safr04-T(110):T(78)

所以你看,如果你在嵌套循环中这样做,你将更容易接近你的目标 - 至少更接近一步。但是你似乎在寻找一种处理数据的逻辑,而没有告诉我们你的数据背后的逻辑。

通过代码,你已经可以匹配列表并比较field1中的字母与field2的匹配,但是field3的数字如何影响你的输出还不清楚。

无论如何,我希望这至少能有点帮助。


0
这是我的解决方案。用您想要检查的任何成对位点替换pair变量。我将行的索引添加到元组中,以防排序很重要。
import csv

snp_file = open('input.txt', 'r')
snps = csv.reader(snp_file, delimiter=',')
pair=(1,2)#the choosen pair

dic={}
i=0
for row in snps:
    if row==[]: break
    locus=int(row[0][len('locus_'):])
    safr=int(row[1][len('>safr'):])
    letter=row[2]
    number=row[3]
    index=i
    if (locus, safr) in dic:
        dic[locus, safr].append((letter, number, index))
    else:
        dic[locus, safr]=[(letter, number, index)]
    i+=1

for key in dic:
    if key[0]==pair[0] and (pair[1], key[1]) in dic:
        for e in dic[key]:
            for f in dic[pair[1], key[1]]:
                print e, ' ', f

这将产生以下输出:

('R', '104', 0)   ('Y', '15', 9)
('R', '104', 0)   ('T', '78', 13)
('K', '110', 4)   ('Y', '15', 9)
('K', '110', 4)   ('T', '78', 13)
('A', '104', 2)   ('Y', '15', 10)
('A', '104', 2)   ('T', '78', 14)
('T', '110', 6)   ('Y', '15', 10)
('T', '110', 6)   ('T', '78', 14)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接