Как связать два зависимых ввода неизвестного размера с переменными

Это мой первый скрипт на python. Мои данные выглядят так:

Position ind1 ind2 ind3 ind4 ind5 ind5 ind7 ind8
 0        C    A     C   A    A    A    A     A
 1        C    A     C   C    C    A    A     A

но он может варьироваться по количеству столбцов и имеет тысячи строк.

Мой сценарий, который делает то, что мне нужно, читает этот файл построчно и вычисляет частоту A и C для комбинации людей (в дальнейшем население) в каждой позиции (POS). Например, частота А в положении 0 для населения 1 (ind1, ind2, ind3, ind4); и частота А в положении 0 для населения 2 (ind5, ind6, ind7, ind8), то же самое для POS 1, 2, 3 ....

Для этого я определяю комбинацию столбцов (совокупностей) в моем скрипте следующим кодом:

alleles1 = alleles[1:5]
alleles2 = alleles[5:]

но если у меня более 9 столбцов и различные комбинации столбцов, мне нужно изменить аллели * и остальную часть сценария после этого.

Я хочу сделать мою программу более интерактивной, чтобы пользователь определял количество популяций и определял, какой столбец соответствует какому населению.

Код у меня так далеко:

#ask for the number of populations
try:
    num_pop = int(raw_input("How many populations do you have? > "))
except ValueError:
    print "In is not an integer! \nThe program exits...\n "
#ask for individuals in population
ind_pop = {}
for i in range(num_pop):
    i += 1
    ind_input = str(raw_input("Type column numbers of population %i > " % i))
    ind_pop[i] = re.findall(r'[^,;\s]+', ind_input)

если у меня 2 популяции, где столбцы 3, 5, 6 - это население 1, а столбцы 2, 5 - это население 2. Это работает следующим образом:

> How many populations do you have? > 2
> Type column numbers of population 1 > 3, 5, 6  
> Type column numbers of population 2 > 2, 4 

Входные данные хранятся в словаре.

{1: ['3', '5', '6'], 2: ['2', '4']}

Вопрос в том, как перейти от этого ввода к определению аллелей. Вывод должен быть таким:

allele1 =  [allele[3], allele[5], allele[6]]
allele2 =  [allele[2], allele[4]]

Если это необходимо, вот основные части остальной части кода:

with open('test_file.txt') as datafile:
  next(datafile)
  for line in datafile:
    words = line.split() #splits string into the list of words 
    chr_pos = words[0:2] #select column chromosome and position
    alleles = words[2:] # this and next separates alleles for populations

    alleles1 = alleles[0:4]
    alleles2 = alleles[4:8]
    alleles3 = alleles[8:12]
    alleles4 = alleles[12:16]

    counter1=collections.Counter(alleles1)
    counter2=collections.Counter(alleles1)
    counter3=collections.Counter(alleles1)
    counter4=collections.Counter(alleles1)
#### the rest of the code and some filters within the part above were spiked

3 ответа

Решение

Сначала нужно преобразовать номера столбцов в целые числа

    ind_pop[i] = [int(j) for j in re.findall(r'[^,;\s]+', ind_input)]

(Я бы также изменил ваше регулярное выражение на r'\d+')

Тогда вместо того, чтобы alleles1, alleles2 и т.д., иметь основной список или словарь:

master = {i: [alleles[j] for j in vals] for i, vals in ind_pop.items()}
counters = {i: collections.Counter(al) for i, al in master.items()}

Тогда вы можете получить доступ counters[i] вместо counter1 и т.п.

Как примечание, вы, вероятно, можете упростить все вышеперечисленное, сделав ind_pop в список, используя append вместо того чтобы держать счетчик

Спасибо за предложения. Некоторые из них были полезны. Я чувствую, что мне нужно изменить направление. Я буду продолжать работать со списком списка:

pop_alleles = []
for key in ind_pop.keys():
  pop_alleles.append([alleles[el] for el in ind_pop[key]])

Если это выход, который вы ищете,

allele1 =  [allele[3], allele[5], allele[6]]
allele2 =  [allele[2], allele[4]]

и у вас есть это:

{1: ['3', '5', '6'], 2: ['2', '4']}

это довольно просто отсюда.

for index in population_dict[1]:
    allele1.append(allele[index])
for index in population_dict[2]:
    allele2.append(allele[index])

О, если индексы хранятся в виде строк, так как они выглядят так, как если бы они были выше, вам сначала нужно сделать их целочисленными. Вы можете изменить вышеприведенное на аллель [int(index)], но было бы лучше просто превратить их в целые, когда вы их читаете.

Другие вопросы по тегам