Взвешенная случайная выборка для моделирования Монте-Карло в R - PullRequest
0 голосов
/ 29 июня 2019

Я хотел бы запустить симуляцию Монте-Карло.У меня есть data.frame, где строки являются уникальными идентификаторами, которые имеют вероятность ассоциации с одним из столбцов.Данные, введенные в столбцы, могут рассматриваться как весовые коэффициенты для этой вероятности.Я хочу случайным образом sample каждую строку в data.frame на основе весов, перечисленных для каждой строки.Каждая строка должна возвращать только одно значение за цикл.Структура data.frame выглядит следующим образом:

ID,    X2000,  X2001,  X2002,  X2003,  X2004
X11,   0,      0,      0.5,    0.5,    0
X33,   0.25,   0.25,   0.25,   0.25,   0
X55,   0,      0,      0,      0,      1
X77,   0.5,    0,      0,      0,      0.5

Для взвешивания «X11» должен возвращать либо X2002, либо X2003, «X33» должен иметь равную вероятность возврата X2000, X2001, X2002 или X2003,должно быть равным без шансов вернуть X2004.Единственный возможный возврат для «X55» должен быть X2004.

Интересующие меня выходные данные - это идентификаторы и столбец, который был выбран для этого прогона, хотя, вероятно, было бы проще вернуть что-то вроде этого:

ID,    X2000,  X2001,  X2002,  X2003,  X2004
X11,   0,      0,      1,      0,      0
X33,   1,      0,      0,      0,      0
X55,   0,      0,      0,      0,      1
X77,   1,      0,      0,      0,      0

1 Ответ

1 голос
/ 30 июня 2019

Ваш data.frame транспонирован - функция sample() принимает вектор вероятности. Тем не менее, ваш вектор вероятности находится в ряду, что означает, что его сложнее извлечь из data.frame.

Чтобы обойти это, вы можете импортировать ваш столбец идентификаторов в виде row.name. Это позволяет вам иметь доступ к нему во время оператора apply(). Обратите внимание, что apply() приведет data.frame к матрице, что означает, что разрешен только один тип данных. Вот почему идентификаторы должны быть именами строк - иначе у нас был бы вектор вероятности символов вместо чисел.

mc_df <- read.table(
text = 
'ID    X2000  X2001  X2002  X2003  X2004
X11   0      0      0.5    0.5    0
X33   0.25   0.25   0.25   0.25   0
X55   0      0      0      0      1
X77   0.5    0      0      0      0.5'
                    , header = T
                    ,row.names = 1)

Оттуда можно использовать функцию применения:

apply(mc_df, 1, function(x) sample(names(x), size = 200, replace = T, prob = x))

Или вы можете сделать это необычным

apply(mc_df, 1, function(x) table(sample(names(x), size = 200, replace = T, prob = x)))

$X11

X2002 X2003 
  102    98 

$X33

X2000 X2001 X2002 X2003 
   54    47    64    35 

$X55

X2004 
  200 

$X77

X2000 X2004 
  103    97 

навороченные:

apply(mc_df, 1, function(x) table(sample(as.factor(names(x)), size = 200, replace = T, prob = x)))
      X11 X33 X55 X77
X2000   0  51   0  99
X2001   0  50   0   0
X2002  91  57   0   0
X2003 109  42   0   0
X2004   0   0 200 101

Или причудливый:

prop.table(apply(mc_df
                 , 1
                 , function(x) table(sample(as.factor(names(x)), size = 200, replace = T, prob = x)))
           ,2)
       X11   X33 X55   X77
X2000 0.00 0.270   0 0.515
X2001 0.00 0.235   0 0.000
X2002 0.51 0.320   0 0.000
X2003 0.49 0.175   0 0.000
X2004 0.00 0.000   1 0.485
...