Подходящие распределения, качество подгонки, p-значение. Можно ли это сделать с помощью Scipy (Python)?

ВВЕДЕНИЕ: Я биоинформатик. В своем анализе, который я выполняю на всех генах человека (около 20 000), я ищу конкретный мотив короткой последовательности, чтобы проверить, сколько раз этот мотив встречается в каждом гене.

Гены «записаны» в линейной последовательности из четырех букв (A,T,G,C). Например: CGTAGGGGGTTTAC... Это четырехбуквенный алфавит генетического кода, который подобен тайному языку каждой клетки, именно так ДНК хранит информацию.

Я подозреваю, что частые повторения определенной последовательности короткого мотива (AGTGGAC) в некоторых генах имеют решающее значение для определенного биохимического процесса в клетке. Поскольку сам мотив очень короткий, с помощью вычислительных инструментов трудно отличить истинные функциональные примеры в генах от тех, которые выглядят похожими случайно. Чтобы избежать этой проблемы, я получаю последовательности всех генов, объединяю их в одну строку и перемешиваю. Длина каждого исходного гена сохранялась. Затем для каждой исходной длины последовательности была построена случайная последовательность путем многократного случайного выбора A, T, G или C из объединенной последовательности и переноса ее в случайную последовательность. Таким образом, результирующий набор рандомизированных последовательностей имеет одинаковое распределение длины, а также общий состав A, T, G, C. Затем я ищу мотив в этих рандомизированных последовательностях. Я проделал эту процедуру 1000 раз и усреднил результаты.

  • 15000 генов, не содержащих заданный мотив
  • 5000 генов, содержащих 1 мотив
  • 3000 генов, содержащих 2 мотива
  • 1000 генов, содержащих 3 мотива
  • ...
  • 1 ген, содержащий 6 мотивов

Таким образом, даже после 1000-кратной рандомизации истинного генетического кода не осталось генов, содержащих более 6 мотивов. Но в истинном генетическом коде есть несколько генов, которые содержат более 20 вхождений мотива, что позволяет предположить, что эти повторения могут быть функциональными, и маловероятно, что они будут обнаружены в таком изобилии по чистой случайности.

ПРОБЛЕМА:

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

Могу ли я сделать такой анализ в Python?

Любая помощь будет оценена по достоинству.


person s_sherly    schedule 07.07.2011    source источник
comment
Обратите внимание, что вы существенно изменили свой вопрос. Можно ли вернуть этот вопрос к исходному вопросу плюс четкий раздел «обновления» для всех новых деталей? Или, может быть, просто новый вопрос? Спасибо   -  person eat    schedule 08.07.2011
comment
Вы можете задать этот вопрос в BioStar.   -  person ars    schedule 08.07.2011
comment
Я задаю новый вопрос: stackoverflow.com/questions/6620471/   -  person s_sherly    schedule 08.07.2011


Ответы (2)


В документации SciPy вы найдете список всех реализованы непрерывные функции распределения. У каждого есть метод fit(), который возвращает соответствующие параметры фигуры.

Даже если вы не знаете, какой дистрибутив использовать, вы можете попробовать несколько дистрибутивов одновременно и выбрать тот, который лучше подходит для ваших данных, как в приведенном ниже коде. Учтите, что если вы не имеете представления о распределении, может быть сложно подобрать образец.

введите здесь описание изображения

import matplotlib.pyplot as plt
import scipy
import scipy.stats
size = 20000
x = scipy.arange(size)
# creating the dummy sample (using beta distribution)
y = scipy.int_(scipy.round_(scipy.stats.beta.rvs(6,2,size=size)*47))
# creating the histogram
h = plt.hist(y, bins=range(48))

dist_names = ['alpha', 'beta', 'arcsine',
              'weibull_min', 'weibull_max', 'rayleigh']

for dist_name in dist_names:
    dist = getattr(scipy.stats, dist_name)
    params = dist.fit(y)
    arg = params[:-2]
    loc = params[-2]
    scale = params[-1]
    if arg:
        pdf_fitted = dist.pdf(x, *arg, loc=loc, scale=scale) * size
    else:
        pdf_fitted = dist.pdf(x, loc=loc, scale=loc) * size
    plt.plot(pdf_fitted, label=dist_name)
    plt.xlim(0,47)
plt.legend(loc='upper left')
plt.show()

Использованная литература:

- Настройка дистрибутива с помощью Scipy

- Подгонка эмпирического распределения к теоретическому с помощью Scipy (Python)?

person Saullo G. P. Castro    schedule 20.05.2013
comment
Приведенный выше код выдает мне следующее сообщение об ошибке: AttributeError: объект 'module' не имеет атрибута 'arcsineweibull_min' в операторе dist = getattr(scipy.stats, dist_name). Мои версии: scipy — 0.13.3, numpy — 1.8.0, matplotlib — 1.3.1. - person srodriguex; 16.01.2015
comment
@srodriguex спасибо! Была небольшая опечатка, я ее исправил - person Saullo G. P. Castro; 17.01.2015
comment
@SaulloCastro Как я могу применить эту функцию fit() для подгонки 3D-поверхности, которую я только что добился, используя scipy.linalg.lstsq? Как я могу подтвердить, что у меня есть хорошее соответствие данным. Спасибо. - person diffracteD; 05.05.2015
comment
Этот пример больше не работает должным образом, вы можете его обновить? - person Khris; 28.06.2019
comment
@Khris Я постараюсь найти время, чтобы поработать над этим. Не стесняйтесь редактировать, если вы уже знаете, что несовместимо с новым пакетом SciPy... - person Saullo G. P. Castro; 29.06.2019
comment
@SaulloG.P.Castro Хорошо, я играл с этим. Код все еще работает, но arcsine-подгонка по какой-то причине нарушена. Возможно изменения в вызове функции. Также другие функции выглядят немного иначе, чем на вашем изображении, теперь они подходят намного лучше. - person Khris; 01.07.2019
comment
@Khris хорошо, надеюсь, что ответ был полезен для вас .... Я посмотрю на эти обновления, как только найду время, с уважением - person Saullo G. P. Castro; 01.07.2019

import numpy as np
import pandas as pd
import scipy.stats as st
import statsmodels.api as sm
import matplotlib as mpl
import matplotlib.pyplot as plt
import math
import random

mpl.style.use("ggplot")

def danoes_formula(data):
    """
    DANOE'S FORMULA
    https://en.wikipedia.org/wiki/Histogram#Doane's_formula
    """
    N = len(data)
    skewness = st.skew(data)
    sigma_g1 = math.sqrt((6*(N-2))/((N+1)*(N+3)))
    num_bins = 1 + math.log(N,2) + math.log(1+abs(skewness)/sigma_g1,2)
    num_bins = round(num_bins)
    return num_bins

def plot_histogram(data, results, n):
    ## n first distribution of the ranking
    N_DISTRIBUTIONS = {k: results[k] for k in list(results)[:n]}

    ## Histogram of data
    plt.figure(figsize=(10, 5))
    plt.hist(data, density=True, ec='white', color=(63/235, 149/235, 170/235))
    plt.title('HISTOGRAM')
    plt.xlabel('Values')
    plt.ylabel('Frequencies')

    ## Plot n distributions
    for distribution, result in N_DISTRIBUTIONS.items():
        # print(i, distribution)
        sse = result[0]
        arg = result[1]
        loc = result[2]
        scale = result[3]
        x_plot = np.linspace(min(data), max(data), 1000)
        y_plot = distribution.pdf(x_plot, loc=loc, scale=scale, *arg)
        plt.plot(x_plot, y_plot, label=str(distribution)[32:-34] + ": " + str(sse)[0:6], color=(random.uniform(0, 1), random.uniform(0, 1), random.uniform(0, 1)))
    
    plt.legend(title='DISTRIBUTIONS', bbox_to_anchor=(1.05, 1), loc='upper left')
    plt.show()

def fit_data(data):
    ## st.frechet_r,st.frechet_l: are disbled in current SciPy version
    ## st.levy_stable: a lot of time of estimation parameters
    ALL_DISTRIBUTIONS = [        
        st.alpha,st.anglit,st.arcsine,st.beta,st.betaprime,st.bradford,st.burr,st.cauchy,st.chi,st.chi2,st.cosine,
        st.dgamma,st.dweibull,st.erlang,st.expon,st.exponnorm,st.exponweib,st.exponpow,st.f,st.fatiguelife,st.fisk,
        st.foldcauchy,st.foldnorm, st.genlogistic,st.genpareto,st.gennorm,st.genexpon,
        st.genextreme,st.gausshyper,st.gamma,st.gengamma,st.genhalflogistic,st.gilbrat,st.gompertz,st.gumbel_r,
        st.gumbel_l,st.halfcauchy,st.halflogistic,st.halfnorm,st.halfgennorm,st.hypsecant,st.invgamma,st.invgauss,
        st.invweibull,st.johnsonsb,st.johnsonsu,st.ksone,st.kstwobign,st.laplace,st.levy,st.levy_l,
        st.logistic,st.loggamma,st.loglaplace,st.lognorm,st.lomax,st.maxwell,st.mielke,st.nakagami,st.ncx2,st.ncf,
        st.nct,st.norm,st.pareto,st.pearson3,st.powerlaw,st.powerlognorm,st.powernorm,st.rdist,st.reciprocal,
        st.rayleigh,st.rice,st.recipinvgauss,st.semicircular,st.t,st.triang,st.truncexpon,st.truncnorm,st.tukeylambda,
        st.uniform,st.vonmises,st.vonmises_line,st.wald,st.weibull_min,st.weibull_max,st.wrapcauchy
    ]
    
    MY_DISTRIBUTIONS = [st.beta, st.expon, st.norm, st.uniform, st.johnsonsb, st.gennorm, st.gausshyper]

    ## Calculae Histogram
    num_bins = danoes_formula(data)
    frequencies, bin_edges = np.histogram(data, num_bins, density=True)
    central_values = [(bin_edges[i] + bin_edges[i+1])/2 for i in range(len(bin_edges)-1)]

    results = {}
    for distribution in MY_DISTRIBUTIONS:
        ## Get parameters of distribution
        params = distribution.fit(data)
        
        ## Separate parts of parameters
        arg = params[:-2]
        loc = params[-2]
        scale = params[-1]
    
        ## Calculate fitted PDF and error with fit in distribution
        pdf_values = [distribution.pdf(c, loc=loc, scale=scale, *arg) for c in central_values]
        
        ## Calculate SSE (sum of squared estimate of errors)
        sse = np.sum(np.power(frequencies - pdf_values, 2.0))
        
        ## Build results and sort by sse
        results[distribution] = [sse, arg, loc, scale]
        
    results = {k: results[k] for k in sorted(results, key=results.get)}
    return results
        
def main():
    ## Import data
    data = pd.Series(sm.datasets.elnino.load_pandas().data.set_index('YEAR').values.ravel())
    results = fit_data(data)
    plot_histogram(data, results, 5)

if __name__ == "__main__":
    main()
    
    

введите здесь описание изображения

person Sebastian Jose    schedule 16.02.2021