Моделирование данных в R с несколькими распределениями вероятностей

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

Я очень признателен всем, кто может помочь ответить на вопрос или помочь мне сформулировать вопрос более четко.

Моя проблема заключается в написании соответствующего кода R для более сложной формы моделирования данных.

Текущий код:

n <- 1e4
set.seed(42)
sims <- sapply(1:80, 
               function(k) 
                 rowSums(
                   replicate(k, sample((1:7)/10, n, TRUE, ps))) / k)

Этот код имитирует данные, где каждая точка данных имеет значение, которое является средним значением между 1:80 наблюдениями. Например, когда значения точек данных являются средним значением 10 наблюдений (k = 10), он случайным образом выбирает 10 значений (которые могут быть 0,1,0,2,0,3, 0,4, 0,5,0,6 или 0,7) на основе распределения вероятностей. ps, который дает вероятность каждого значения (на основе всего эмпирического распределения).

ps выглядит так:

ps <- prop.table(table((DF$mean_score)[DF$total_number_snps == 1]))
#        0.1         0.2         0.3         0.4         0.5         0.6         0.7 
#0.582089552 0.194029851 0.124378109 0.059701493 0.029850746 0.004975124 0.004975124 

например, вероятность того, что значение наблюдения 0.1, равна 0.582089552.

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

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

Пример таблицы cond_probs:

gene_name   0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 total
A1  0.664   0.319   0.018   0.000   0.000   0.000   0.000   0.000   0.000   113.000
A2  0.000   1.000   0.000   0.000   0.000   0.000   0.000   0.000   0.000   1.000

Таким образом, для точки данных A2 существует только 1 наблюдение, которое имеет значение 0.1. Следовательно, частота 0.1 наблюдений 1. Для A1 имеется 113 наблюдений, и большинство из них (0.664) имеют значение 0.1. Идея состоит в том, что cond_probs похож на ps, но cond_probs имеет распределение вероятностей для каждой точки данных, а не одно для всех данных.

Я хотел бы изменить приведенный выше код, чтобы в выборке использовалось cond_probs вместо ps для частотного распределения. И использовать количество наблюдений k в качестве критерия при выборе строки в cond_probs для выборки. Итак, это будет работать так:

Для точек данных с k количеством наблюдений:

посмотрите в cond_probs таблицу и случайным образом выберите строку, в которой total количество наблюдений по размеру совпадает с k: 0.9k-1.1k. Если таких строк нет, продолжайте.

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

Для каждой из n итераций replicate произвольно выбирайте с заменой новую точку данных из cond_probs из всех строк, где значение total похоже на текущее значение k (0.9k-1.1k).

Идея состоит в том, что для этого набора данных необходимо определить, какое распределение вероятностей использовать на основе количества наблюдений, лежащих в основе точки данных. Это связано с тем, что в этом наборе данных вероятность наблюдения зависит от количества наблюдений (гены с большим количеством SNP, как правило, имеют более низкий балл за наблюдение из-за генетической связи и фонового отбора).

ОБНОВЛЕНИЕ С ИСПОЛЬЗОВАНИЕМ ОТВЕТА НИЖЕ:

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

cond_probs <- read.table("cond_probs.txt", header = TRUE, check.names = FALSE)
cond_probs <- as.matrix(cond_probs)

а в первом примере десять строк (из ~ 20000 строк) выглядят так:

>cond_probs
       total   0.1   0.2   0.3   0.4   0.5   0.6   0.7   0.8   0.9   1.0
[1,]     109 0.404 0.174 0.064 0.183 0.165 0.009 0.000 0.000 0.000 0.000
[2,]     181 0.564 0.221 0.144 0.066 0.006 0.000 0.000 0.000 0.000 0.000
[3,]     289 0.388 0.166 0.118 0.114 0.090 0.093 0.028 0.003 0.000 0.000
[4,]     388 0.601 0.214 0.139 0.039 0.008 0.000 0.000 0.000 0.000 0.000
[5,]     133 0.541 0.331 0.113 0.000 0.008 0.008 0.000 0.000 0.000 0.000
[6,]     221 0.525 0.376 0.068 0.032 0.000 0.000 0.000 0.000 0.000 0.000
[7,]     147 0.517 0.190 0.150 0.054 0.034 0.048 0.007 0.000 0.000 0.000
[8,]     107 0.458 0.196 0.252 0.084 0.009 0.000 0.000 0.000 0.000 0.000
[9,]      13 0.846 0.154 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000

Если я бегу:

sampleSize <- 20
set.seed(42)
#replace 1:80 with 1: max number of SNPs in gene in dataset
sims_test <- sapply( 1:50, simulateData, sampleSize )

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

Например:

> sims_test[[31]]
[1] 0.1

И sims_test заказывается не так, как sims:

>sims_test
   [,1] [,2]      [,3]  [,4] [,5]      [,6]      [,7]   [,8]      [,9]
 [1,]  0.1  0.1 0.1666667 0.200 0.14 0.2666667 0.2000000 0.2375 0.1888889
 [2,]  0.1  0.1 0.1333333 0.200 0.14 0.2333333 0.1571429 0.2625 0.1222222
 [3,]  0.1  0.1 0.3333333 0.225 0.14 0.1833333 0.2285714 0.2125 0.1555556
 [4,]  0.1  0.1 0.2666667 0.250 0.10 0.1500000 0.2000000 0.2625 0.2777778
 [5,]  0.1  0.1 0.3000000 0.200 0.16 0.2000000 0.2428571 0.1750 0.1000000
 [6,]  0.1  0.1 0.3666667 0.250 0.16 0.1666667 0.2142857 0.2500 0.2000000
 [7,]  0.1  0.1 0.4000000 0.300 0.12 0.2166667 0.1857143 0.2375 0.1666667
 [8,]  0.1  0.1 0.4000000 0.250 0.10 0.2500000 0.2714286 0.2375 0.2888889
 [9,]  0.1  0.1 0.1333333 0.300 0.14 0.1666667 0.1714286 0.2750 0.2888889

ОБНОВЛЕНИЕ 2

Используя cond_probs <- head(cond_probs,n), я определил, что код работает до n = 517, а затем для всех размеров больше этого он дает тот же результат, что и выше. Я не уверен, проблема ли это в самом файле или проблема с памятью. Я обнаружил, что если я удалю строку 518 и продублирую строки до этого несколько раз, чтобы сделать файл большего размера, это сработает, предполагая, что сама строка вызывает проблему. Строка 518 выглядит так:

9.000   0.889   0.000   0.000   0.000   0.111   0.000   0.000   0.000   0.000   0.000

Я нашел еще 4 оскорбительные строки:

9.000   0.444   0.333   0.111   0.111   0.000   0.000   0.000   0.000   0.000   0.000

9.000   0.444   0.333   0.111   0.111   0.000   0.000   0.000   0.000   0.000   0.000

9.000   0.111   0.222   0.222   0.111   0.111   0.222   0.000   0.000   0.000   0.000

9.000   0.667   0.111   0.000   0.000   0.000   0.222   0.000   0.000   0.000   0.000

Я не замечаю в них ничего необычного. Всего у них 9 сайтов. Если я удалю эти строки и запустил файл cond_probs, содержащий только строки ПЕРЕД этим, код заработает. Но должны быть и другие проблемные строки, так как вся команда cond_probs по-прежнему не работает.

Я попытался поместить эти проблемные строки обратно в меньший файл cond_probs, и этот файл затем заработал, поэтому я очень смущен, поскольку не кажется, что строки изначально проблематичны. С другой стороны, тот факт, что все они имеют 9 сайтов, предполагает некую причинную закономерность.

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

Возникает еще одна проблема: я не уверен, работает ли код должным образом. Я сделал фиктивный файл cond_probs, в котором есть две точки данных с «общим» наблюдением «1»:

total   0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
1.000   0.000   0.000   0.000   0.000   0.000   1.000   0.000   0.000   0.000   0.000
1.000   0.000   1.000   0.000   0.000   0.000   0.000   0.000   0.000   0.000   0.000

Поэтому я ожидал бы, что они оба будут отобраны для точек данных с наблюдением «1» и, следовательно, получат примерно 50% наблюдений со средним значением «0,2» и 50% со средним значением «0,6». Однако среднее значение всегда равно 0,2:

sims_test[[1]]
 [1] 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2

Даже если я сделаю выборку 10000 раз, все наблюдения будут 0,2, а не 0,6. Насколько я понимаю, код должен случайным образом выбирать новую строку из cond_probs с аналогичным размером для каждого наблюдения, но в этом случае, похоже, этого не происходит. Я неправильно понимаю код или все еще проблема с тем, что я ввел неверный код?

Весь файл cond_probs можно найти по следующему адресу:

cond_probs

ОБНОВЛЕНИЕ 3

Изменение sapply на lapply при запуске моделирования устранило эту проблему.

Еще одна причина, по которой я думаю, что оставить cond_probs как есть и выбрать распределение sampleSize количество раз может быть лучшим решением: вероятность выбора распределения должна быть связана с его частотой в cond_probs. Если мы объединим распределения, шансы выбора распределения с total 9 или 10 больше не будут зависеть от количества наблюдений с этими итогами. Пример: Если есть 90 дистрибутивов с total=10 и 10 с total=9, должна быть 90% возможность выбрать дистрибутив с total=10. Если мы объединим распределения, не станут ли шансы 50/50 для выбора распределения с «общим» = 9 или 10 (что не было бы идеальным)?


person user964689    schedule 03.11.2015    source источник
comment
Я бы посоветовал вам поискать bootstrapping и условная вероятность.   -  person Alex W    schedule 07.11.2015
comment
Мне непонятно, как именно вы хотите решить свою проблему и разумно ли предложенное вами решение. Похоже, вы путаете наблюдаемые частоты (условные или иные) в ваших данных с распределением вероятностей ваших данных ... возможно, это разумный подход с помощью начальной загрузки, или, возможно, это не так, и вам следует смотреть на условное апостериорное распределение с информативным / неинформативным априорном .... Я лично просто не понимаю, основываясь на вашем описании   -  person Alex W    schedule 07.11.2015
comment
спасибо за конструктивные комментарии. Вы правы в том, что я был небрежен с терминологией, и это, по сути, метод самозагрузки. Я постараюсь это исправить. Хотя меня все еще смущает разница между распределением вероятностей и наблюдаемыми частотами в эмпирическом распределении. Если я хочу выполнить повторную выборку из эмпирического распределения с вероятностью, основанной на наблюдаемом частотном распределении, не относятся ли частотное распределение и распределение вероятностей к одному и тому же?   -  person user964689    schedule 07.11.2015
comment
Буду рад обсудить дальше в приватном чате   -  person user964689    schedule 07.11.2015
comment
Рассмотрим P (Y | X = x *) ~ N (\ mu, \ sigma) (или некоторую f (\ theta)). Вы наблюдаете y_1, ..., y_10 из такого распределения. Образцы начальной загрузки из y_1, ... y_10 явно не то же самое, что выборка из N (\ mu, \ sigma) или из апостериорного, основанного на предыдущем N (\ mu, \ sigma) и наблюдаемой вероятности из y_1, ... , г_10. Это моя точка зрения. Опять же, возможно, бутстрап подходит для вашей проблемы, «частотное распределение и распределение вероятностей [не] относятся к одному и тому же».   -  person Alex W    schedule 07.11.2015


Ответы (1)


Я просто написал функцию ps, которая выбирает подходящий дистрибутив из cond_probs:

N <- 10  # The sampled values are 0.1, 0.2, ... , N/10
M <- 8   # number of distributions in "cond_probs"

#-------------------------------------------------------------------
# Example data:

set.seed(1)

cond_probs <- matrix(0,M,N)

is.numeric(cond_probs)

for(i in 1:nrow(cond_probs)){ cond_probs[i,] <- dnorm((1:N)/M,i/M,0.01*N) }

is.numeric(cond_probs)

total <- sort( sample(1:80,nrow(cond_probs)) )
cond_probs <- cbind( total, cond_probs/rowSums(cond_probs) )

colnames(cond_probs) <- c( "total", paste("P",1:N,sep="") )

#---------------------------------------------------------------------
# A function that chooses an appropiate distribution from "cond_prob",
# depending on the number of observations "numObs":

ps <- function( numObs,
                similarityLimit = 0.1 )
{
  similar <- which( abs(cond_probs[,"total"] - numObs) / numObs < similarityLimit )

  if ( length(similar) == 0 )
  { 
    return(NA)
  }
  else
  {
    return( cond_probs[similar[sample(1:length(similar),1)],-1] )
  }
}

#-----------------------------------------------------------------
# A function that simulates data using a distribution that is
# appropriate to the number of observations, if possible:

simulateData <- function( numObs, sampleSize )
{
  if (any(is.na(ps(numObs))))
  {
    return (NA)
  }
  else
  {
    return( rowSums(
              replicate(
                numObs,
                replicate( sampleSize, sample((1:N)/10, 1, prob = ps(numObs))))
            ) / numObs )
  }
}

#-----------------------------------------------------------------
# Test:

sampleSize <- 30
set.seed(42)
sims <- lapply( 1:80, simulateData, sampleSize )

Распределения в cond_probs:

    total           P1           P2           P3           P4           P5           P6           P7           P8           P9          P10
[1,]    16 6.654875e-01 3.046824e-01 2.923948e-02 5.881753e-04 2.480041e-06 2.191926e-09 4.060763e-13 1.576900e-17 1.283559e-22 2.189990e-28
[2,]    22 2.335299e-01 5.100762e-01 2.335299e-01 2.241119e-02 4.508188e-04 1.900877e-06 1.680045e-09 3.112453e-13 1.208647e-17 9.838095e-23
[3,]    30 2.191993e-02 2.284110e-01 4.988954e-01 2.284110e-01 2.191993e-02 4.409369e-04 1.859210e-06 1.643219e-09 3.044228e-13 1.182153e-17
[4,]    45 4.407425e-04 2.191027e-02 2.283103e-01 4.986755e-01 2.283103e-01 2.191027e-02 4.407425e-04 1.858391e-06 1.642495e-09 3.042886e-13
[5,]    49 1.858387e-06 4.407417e-04 2.191023e-02 2.283099e-01 4.986746e-01 2.283099e-01 2.191023e-02 4.407417e-04 1.858387e-06 1.642492e-09
[6,]    68 1.642492e-09 1.858387e-06 4.407417e-04 2.191023e-02 2.283099e-01 4.986746e-01 2.283099e-01 2.191023e-02 4.407417e-04 1.858387e-06
[7,]    70 3.042886e-13 1.642495e-09 1.858391e-06 4.407425e-04 2.191027e-02 2.283103e-01 4.986755e-01 2.283103e-01 2.191027e-02 4.407425e-04
[8,]    77 1.182153e-17 3.044228e-13 1.643219e-09 1.859210e-06 4.409369e-04 2.191993e-02 2.284110e-01 4.988954e-01 2.284110e-01 2.191993e-02

Средства раздач:

> cond_probs[,-1] %*% (1:10)/10
          [,1]
[1,] 0.1364936
[2,] 0.2046182
[3,] 0.3001330
[4,] 0.4000007
[5,] 0.5000000
[6,] 0.6000000
[7,] 0.6999993
[8,] 0.7998670

Средство моделирования данных для 31 наблюдения:

> sims[[31]]
 [1] 0.2838710 0.3000000 0.2935484 0.3193548 0.3064516 0.2903226 0.3096774 0.2741935 0.3161290 0.3193548 0.3032258 0.2967742 0.2903226 0.3032258 0.2967742
[16] 0.3129032 0.2967742 0.2806452 0.3129032 0.3032258 0.2935484 0.2935484 0.2903226 0.3096774 0.3161290 0.2741935 0.3161290 0.3193548 0.2935484 0.3032258

Примерное распределение - третье:

> ps(31)
          P1           P2           P3           P4           P5           P6           P7           P8           P9          P10 
2.191993e-02 2.284110e-01 4.988954e-01 2.284110e-01 2.191993e-02 4.409369e-04 1.859210e-06 1.643219e-09 3.044228e-13 1.182153e-17 
person mra68    schedule 04.11.2015
comment
Спасибо. Я попробую и дам вам знать. - person user964689; 05.11.2015
comment
Ваш ответ отлично работает для меня с вашим файлом cond_probs, но не тогда, когда я применяю его к своему фактическому файлу cond_probs. Я обновил ответ, чтобы показать, что происходит, когда я его пробую. Вы знаете, почему мой файл может давать разные результаты? Еще раз спасибо за вашу помощь, я думаю, что это, должно быть, небольшая проблема с форматом файла, которая мешает ему работать. - person user964689; 06.11.2015
comment
Структура cond_probs в точности такая, как хотелось: total должен быть первым столбцом. Я не смог воспроизвести ошибку и улучшил свой ответ результатом теста с использованием матрицы cond_probs в вопросе. Как и ожидалось, результирующий sims_test представляет собой список длиной 50. Но sims_test, показанный в вопросе, выглядит как матрица 9 на 9. Я предлагаю вам скопировать и вставить сценарий в мой ответ и посмотреть, получите ли вы тот же результат. Если да, прочтите еще раз cond_probs из файла и замените его на head(cond_probs,n) с возрастающими числами n. n = 9 - это пример выше. - person mra68; 07.11.2015
comment
Спасибо за комментарии и полезные советы. Я последовал вашим предложениям и обнаружил, что он перестает работать в строке 518. Если я удалю эту строку из первых 600, она будет работать, но все равно весь файл cond_probs не работает, поэтому я предполагаю, что есть и другие исключения. Я добавил оскорбительную строку в вопрос. Есть идеи, что вызывает проблему? - person user964689; 07.11.2015
comment
Я нашел больше оскорбительных строк (см. Обновленный ответ), но когда я помещаю эти строки обратно в меньший файл cond_probs, он не останавливает его работу, поэтому я не уверен, в чем заключается основная проблема. Вы хоть представляете, что это может быть? Я был бы рад отправить вам весь файл (21813 строк), если это поможет (он слишком велик, чтобы вставлять его в вопрос). - person user964689; 07.11.2015
comment
Проблема с total = 1 может быть объяснена порядком, в котором мы выбираем распределение и берем образец. До сих пор мы сначала выбирали распределение, а затем брали образец, используя выбранное распределение. Поскольку nObs равно 1, это происходит только один раз. Следовательно, единственный и единственный образец взят из ОДНОГО из двух возможных распределений. Конечно, мы могли sampleSize раз выбрать возможное распределение, взять выборку размером 1, а затем объединить выбранные значения в выборку размером sampleSize. Но более простой способ добиться этого - объединить все дистрибутивы для заданного sampleSize. - person mra68; 07.11.2015
comment
Благодарю. На самом деле, выбор временного диапазона «sampleSize» возможного распределения - это именно то, что мне нужно. Есть ли более простой вариант - создать файл cond_probs, который уже объединяет распределения для всех наблюдений с заданным «общим»? Я не уверен, что это сработает, поскольку я также хочу выбрать распределения из наблюдений с аналогичным «общим». Но, возможно, я вас неправильно понял. - person user964689; 07.11.2015
comment
Если одно из распределений для данной суммы достаточно похоже, то все они достаточно похожи. Следовательно, мы можем объединить их заранее. - person mra68; 07.11.2015
comment
Итак, вы предлагаете объединять только те распределения, которые имеют одинаковое «общее количество»? В этом есть смысл. Это было бы эффективнее, чем выбор времени распределения "выборки"? - person user964689; 07.11.2015
comment
Я добавил ссылку на весь файл cond_probs, размещенный службой загрузки файлов, как вы предложили. - person user964689; 07.11.2015
comment
Я заменил sapply на lapply. Теперь результат всегда будет списком, даже если используется весь файл cond_probs. Я сделаю комбинацию раздач позже. - person mra68; 08.11.2015
comment
Большое спасибо, это фантастическая работа "lapply". Что касается объединения дистрибутивов, я не уверен, будет ли это работать как выбор дистрибутивов "sampleSize" несколько раз. Пример: при выборке для распределений с «10» наблюдениями мы хотим сделать выборку из распределений с «общим» количеством «9», «10» и «11». Этого можно достичь, выбирая распределения a 'sampleSize' количество раз. Количество выбранных распределений должно зависеть от sampleSize, быть независимым от 'nObs' и быть одинаковым для 'nObs'. - person user964689; 08.11.2015
comment
Просто добавил пример в конец вопроса, чтобы попытаться объяснить, почему я думаю, что выбор дистрибутивов, количество раз sampleSize, будет вести себя предпочтительно и иначе, чем комбинирование распределений в cond_probs. Дай мне знать, если я тебя неправильно понял. Спасибо большое. - person user964689; 08.11.2015
comment
Я отредактировал свой ответ. Сейчас раздача выбирается samlpeSize раз. - person mra68; 08.11.2015
comment
Большое вам спасибо, я очень благодарен за это, вы очень мне помогли. - person user964689; 08.11.2015