Я первоначально намеревался использовать MATLAB для занятия этой проблемой, но встроенная функция имеет ограничения, которые не удовлетворяют моей цели. То же ограничение происходит в NumPy.
У меня есть два файла с разделением табуляцией. Первым является файл, показывающий остаток аминокислоты, частоту, и значьте внутреннюю базу данных структур белка, т.е.
A 0.25 1
S 0.25 1
T 0.25 1
P 0.25 1
Второй файл состоит из квадруплетных аминокислот и количества раз, они происходят, т.е.
ASTP 1
Отметьте, существует> 8 000 таких квадруплетных.
На основе фоновой частоты происшествия каждой аминокислоты и количества квадруплетных, я стремлюсь вычислять функцию плотности вероятности многочлена для каждого квадруплета и впоследствии использовать его в качестве математического ожидания в вычислении наибольшего правдоподобия.
Полиномиальное распределение следующие:
f(x|n, p) = n!/(x1!*x2!*...*xk!)*((p1^x1)*(p2^x2)*...*(pk^xk))
то, где x является количеством каждого из k результатов в пробных версиях n с фиксированными вероятностями p. n, является 4 четыре во всех случаях в моем вычислении.
Я создал четыре функции для вычисления этого распределения.
# functions for multinomial distribution
def expected_quadruplets(x, y):
expected = x*y
return expected
# calculates the probabilities of occurence raised to the number of occurrences
def prod_prob(p1, a, p2, b, p3, c, p4, d):
prob_prod = (pow(p1, a))*(pow(p2, b))*(pow(p3, c))*(pow(p4, d))
return prob_prod
# factorial() and multinomial_coefficient() work in tandem to calculate C, the multinomial coefficient
def factorial(n):
if n <= 1:
return 1
return n*factorial(n-1)
def multinomial_coefficient(a, b, c, d):
n = 24.0
multi_coeff = (n/(factorial(a) * factorial(b) * factorial(c) * factorial(d)))
return multi_coeff
Проблема состоит в том, как лучше всего структурировать данные для занятия вычислением наиболее эффективно способом, который я могу считать (Вы, парни пишут некоторый загадочный код :-)) и это не создаст водосливную или ошибку периода выполнения.
До настоящего времени мои данные представлены как вложенные списки.
amino_acids = [['A', '0.25', '1'], ['S', '0.25', '1'], ['T', '0.25', '1'], ['P', '0.25', '1']]
quadruplets = [['ASTP', '1']]
Я первоначально намеревался вызвать эти функции во вложенном для цикла, но это привело к ошибкам периода выполнения или водосливным ошибкам. Я знаю, что могу сбросить предел рекурсии, но я сделал бы это более изящно.
У меня было следующее:
for i in quadruplets:
quad = i[0].split(' ')
for j in amino_acids:
for k in quadruplets:
for v in k:
if j[0] == v:
multinomial_coefficient(int(j[2]), int(j[2]), int(j[2]), int(j[2]))
Я haven'te, действительно полученный к тому, как включить другие функции все же. Я думаю, что мое текущее вложенное расположение списка sub оптимальный.
Я хочу сравнить каждую букву в строке 'ASTP' с первым компонентом каждого списка sub в amino_acids. Где соответствие существует, я хочу передать соответствующие числовые значения функциям с помощью индексов.
Их лучший путь? Я могу добавить соответствующие числа для каждой аминокислоты и квадруплета к временной структуре данных в цикле, передать это функциям и очистить его для следующего повторения?
Спасибо, S :-)
Это может иметь отношение к вашему исходному вопросу, но я настоятельно не рекомендую явно вычислять факториалы из-за переполнения. Вместо этого воспользуйтесь тем фактом, что факториал (n)
= гамма (n + 1)
, используйте логарифм гамма-функции и используйте сложение вместо умножения, вычитание вместо деления . scipy.special
содержит функцию с именем gammaln
, которая дает логарифм гамма-функции.
from itertools import izip
from numpy import array, log, exp
from scipy.special import gammaln
def log_factorial(x):
"""Returns the logarithm of x!
Also accepts lists and NumPy arrays in place of x."""
return gammaln(array(x)+1)
def multinomial(xs, ps):
n = sum(xs)
xs, ps = array(xs), array(ps)
result = log_factorial(n) - sum(log_factorial(xs)) + sum(xs * log(ps))
return exp(result)
Если вы не хотите устанавливать SciPy только ради gammaln
, вот замена на чистом Python (конечно, он медленнее и не векторизован, как в SciPy):
def gammaln(n):
"""Logarithm of Euler's gamma function for discrete values."""
if n < 1:
return float('inf')
if n < 3:
return 0.0
c = [76.18009172947146, -86.50532032941677, \
24.01409824083091, -1.231739572450155, \
0.001208650973866179, -0.5395239384953 * 0.00001]
x, y = float(n), float(n)
tm = x + 5.5
tm -= (x + 0.5) * log(tm)
se = 1.0000000000000190015
for j in range(6):
y += 1.0
se += c[j] / y
return -tm + log(2.5066282746310005 * se / x)
Другой простой прием - использовать dict
для amino_acids
, индексируемый самим остатком. Учитывая вашу исходную структуру amino_acids
, вы можете сделать следующее:
amino_acid_dict = dict((amino_acid[0], amino_acid) for amino_acid in amino_acids)
print amino_acid_dict
{"A": ["A", 0.25, 1], "S": ["S", 0.25, 1], "T": ["T", 0.25, 1], "P": ["P", 0.25, 1]}
Затем вы можете проще искать частоты или счетчики по остатку:
freq_A = amino_acid_dict["A"][1]
count_A = amino_acid_dict["A"][2]
Это сэкономит вам время в основном цикле:
for quadruplet in quadruplets:
probs = [amino_acid_dict[aa][1] for aa in quadruplet]
counts = [amino_acid_dict[aa][2] for aa in quadruplet]
print quadruplet, multinomial(counts, probs)