如何在python列表中存储多个类别组合(72个变量)
我将数据存储在列表中,列表的组织方式如下:如何在python列表中存储多个类别组合(72个变量),python,Python,我将数据存储在列表中,列表的组织方式如下: lst = [ ['FHControl', G, A] ['MNHDosed', G, C] ] 对于lst:row[0]中的行,总共有12个类别(我在上面的示例代码中列出了两个)。对于第[1]行和第[2]行,我只关注这些字母组合中的6个。因此,我在lst中每行有72个可能的数据组合,并且需要计算每个组合的实例,而不必编写几十个嵌套的if循环 我试图创建两个函数来解析这些列表,并对这72种组合的发生率进行分类。我如
lst = [
['FHControl', G, A]
['MNHDosed', G, C]
]
对于lst:row[0]中的行,总共有12个类别(我在上面的示例代码中列出了两个)。对于第[1]行和第[2]行,我只关注这些字母组合中的6个。因此,我在lst中每行有72个可能的数据组合,并且需要计算每个组合的实例,而不必编写几十个嵌套的if循环
我试图创建两个函数来解析这些列表,并对这72种组合的发生率进行分类。我如何使用下面开始写的两个函数来更新这些变量?我是否需要将字典构造为类变量,以便在迭代这两个函数时可以继续更新它们?任何指导都会很好
下面是我目前使用的代码,它将所有72个变量初始化为6个字典(对于第[1]行和第[2]行中的6个字母组合):
您的代码可以简化为:
TEMP = dict.fromkeys('''FHDosed FHControl FNHDosed FNHControl FTDosed FTControl MHDosed
MHControl MNHDosed MNHControl MTDosed MTControl'''.split(), 0)
TRI_1, TRI_2, TRV_1, TRV_2, TRV_3, TRV_4 = [TEMP.copy() for i in range(6)]
dmap = {
('G', 'A'): TRI_1,
('C', 'T'): TRI_1,
('A', 'G'): TRI_2,
('T', 'C'): TRI_2,
('G', 'C'): TRV_1,
('C', 'G'): TRV_1,
('A', 'T'): TRV_1,
('T', 'A'): TRV_1,
}
for row in lst:
key, q, s = row
dmap[q, s][key] += 1
另一种可能性是使用一个或多个dict而不是6个dict:
TEMP = dict.fromkeys('''FHDosed FHControl FNHDosed FNHControl FTDosed FTControl MHDosed
MHControl MNHDosed MNHControl MTDosed MTControl'''.split(), 0)
TR = {key:TEMP.copy() for key in ('TRI_1', 'TRI_2', 'TRV_1', 'TRV_2', 'TRV_3', 'TRV_4')}
dmap = {
('G', 'A'): 'TRI_1',
('C', 'T'): 'TRI_1',
('A', 'G'): 'TRI_2',
('T', 'C'): 'TRI_2',
('G', 'C'): 'TRV_1',
('C', 'G'): 'TRV_1',
('A', 'T'): 'TRV_1',
('T', 'A'): 'TRV_1',
}
lst = [
['FHControl', 'G', 'A'],
['MNHDosed', 'G', 'C']
]
for row in lst:
key, q, s = row
TR[dmap[q, s]][key] += 1
print(TR)
这样做的好处是命名空间中的dict更少,而且以后使用dict of dict而不是硬编码6 dict可能更容易重构代码
根据午夜的建议,如果您有,您可以用数据帧替换dict of dict。然后可以使用以下公式计算对的频率:
import pandas as pd
dmap = {
'GA': 'TRI_1',
'CT': 'TRI_1',
'AG': 'TRI_2',
'TC': 'TRI_2',
'GC': 'TRV_1',
'CG': 'TRV_1',
'AT': 'TRV_1',
'TA': 'TRV_1',
}
lst = [
['FHControl', 'G', 'A'],
['MNHDosed', 'G', 'C']
]
df = pd.DataFrame(lst, columns=['key', 'q', 's'])
df['tr'] = (df['q']+df['s']).map(dmap)
print(df)
# key q s tr
# 0 FHControl G A TRI_1
# 1 MNHDosed G C TRV_1
print(pd.crosstab(rows=[df['key']], cols=[df['tr']]))
屈服
tr TRI_1 TRV_1
key
FHControl 1 0
MNHDosed 0 1
您的代码可以简化为:
TEMP = dict.fromkeys('''FHDosed FHControl FNHDosed FNHControl FTDosed FTControl MHDosed
MHControl MNHDosed MNHControl MTDosed MTControl'''.split(), 0)
TRI_1, TRI_2, TRV_1, TRV_2, TRV_3, TRV_4 = [TEMP.copy() for i in range(6)]
dmap = {
('G', 'A'): TRI_1,
('C', 'T'): TRI_1,
('A', 'G'): TRI_2,
('T', 'C'): TRI_2,
('G', 'C'): TRV_1,
('C', 'G'): TRV_1,
('A', 'T'): TRV_1,
('T', 'A'): TRV_1,
}
for row in lst:
key, q, s = row
dmap[q, s][key] += 1
另一种可能性是使用一个或多个dict而不是6个dict:
TEMP = dict.fromkeys('''FHDosed FHControl FNHDosed FNHControl FTDosed FTControl MHDosed
MHControl MNHDosed MNHControl MTDosed MTControl'''.split(), 0)
TR = {key:TEMP.copy() for key in ('TRI_1', 'TRI_2', 'TRV_1', 'TRV_2', 'TRV_3', 'TRV_4')}
dmap = {
('G', 'A'): 'TRI_1',
('C', 'T'): 'TRI_1',
('A', 'G'): 'TRI_2',
('T', 'C'): 'TRI_2',
('G', 'C'): 'TRV_1',
('C', 'G'): 'TRV_1',
('A', 'T'): 'TRV_1',
('T', 'A'): 'TRV_1',
}
lst = [
['FHControl', 'G', 'A'],
['MNHDosed', 'G', 'C']
]
for row in lst:
key, q, s = row
TR[dmap[q, s]][key] += 1
print(TR)
这样做的好处是命名空间中的dict更少,而且以后使用dict of dict而不是硬编码6 dict可能更容易重构代码
根据午夜的建议,如果您有,您可以用数据帧替换dict of dict。然后可以使用以下公式计算对的频率:
import pandas as pd
dmap = {
'GA': 'TRI_1',
'CT': 'TRI_1',
'AG': 'TRI_2',
'TC': 'TRI_2',
'GC': 'TRV_1',
'CG': 'TRV_1',
'AT': 'TRV_1',
'TA': 'TRV_1',
}
lst = [
['FHControl', 'G', 'A'],
['MNHDosed', 'G', 'C']
]
df = pd.DataFrame(lst, columns=['key', 'q', 's'])
df['tr'] = (df['q']+df['s']).map(dmap)
print(df)
# key q s tr
# 0 FHControl G A TRI_1
# 1 MNHDosed G C TRV_1
print(pd.crosstab(rows=[df['key']], cols=[df['tr']]))
屈服
tr TRI_1 TRV_1
key
FHControl 1 0
MNHDosed 0 1
binner
依赖于两个参数还是三个参数?如果它只依赖于q
和s
这两个看起来是一个字母字符串,那么为什么在调用binner
之前需要像If row[0]='FHDosed'
这样的If语句,而不应该是binner(row[1],row[2])
而不是binner(row[0],row[1],row[2])
?啊,你说得对。我不清楚。我觉得binner应该依赖于三个参数,第一个参数确定应该调用相应字典中的哪个键来修改值(+=1/实例)。if循环使用后两个参数来选择从哪个字典开始。我将编辑代码以反映。无论行[0]
等于什么,对binner
的调用似乎都没有区别。有没有你遗漏的细节?@clintval会是你的选择吗?它正是为这些类型的操作而设计的。binner
依赖于两个参数还是三个参数?如果它只依赖于q
和s
这两个看起来是一个字母字符串,那么为什么在调用binner
之前需要像If row[0]='FHDosed'
这样的If语句,而不应该是binner(row[1],row[2])
而不是binner(row[0],row[1],row[2])
?啊,你说得对。我不清楚。我觉得binner应该依赖于三个参数,第一个参数确定应该调用相应字典中的哪个键来修改值(+=1/实例)。if循环使用后两个参数来选择从哪个字典开始。我将编辑代码以反映。无论行[0]
等于什么,对binner
的调用似乎都没有区别。有没有你遗漏的细节?@clintval会是你的选择吗?它正是为这些类型的操作而设计的。它很有效!这将使将来更容易扩展脚本。我会调查熊猫。。。经过一点阅读,我可能会有更多的应用程序,熊猫将是完美的。荣誉成功了!这将使将来更容易扩展脚本。我会调查熊猫。。。经过一点阅读,我可能会有更多的应用程序,熊猫将是完美的。荣誉