Назначение вероятности для sample () в пределах tapply () - PullRequest
0 голосов
/ 02 февраля 2020

Используя следующее:

name<-c(rep("Adam", times = 6), rep("Barry", times = 4), rep("Charlie", times = 5))
group<-c(1:15)
probs<-c(0.4, 0.2, 0.1, 0.15, 0.1, 0.05, 0.25, 0.35, 0.3, 0.1, 0.2, 0.15, 0.30, 0.15, 0.2)
df<-data.frame(name, group, probs)

Я пытаюсь создать вывод, который берет каждое $ name и назначает ему $ group на основе вероятностей из $ probs. Например, Адам имеет 40% -ную вероятность оказаться в группе 1, 20% -ную вероятность оказаться в группе 2, 10% -ную вероятность оказаться в группе 3 и т. Д. c.

Окончательный результат вернет один группа для каждого имени на основе этих вероятностей и будет выглядеть примерно так

   Adam   Barry Charlie 
      5      10      12 

Я считаю, что я должен использовать tapply () и выполнить следующее, но это не учитывает различные вероятности

tapply(df$group, df$name, sample, 1)

Чтобы использовать различные вероятности, я также попробовал следующее, но он возвращает ошибку из-за неверного числа вероятностей

tapply(df$group, df$name, sample, 1, prob = df$probs)

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

Ответы [ 3 ]

0 голосов
/ 02 февраля 2020

tapply может принимать только вектор, поэтому вам нужно сделать что-то вроде:

0 голосов
/ 02 февраля 2020

Вот базовое решение R, которое не использует tapply, но использует split и sapply. Мы нарисуем образец дважды. Использование set.seed (42) гарантирует, что вы получите те же результаты здесь. Вам не нужно использовать его, когда вы запускаете свои собственные данные:

set.seed(42)
grps <- split(df, df$name)
sapply(grps, function(x) sample(x$group, 1, prob=x$expected_probs))
#    Adam   Barry Charlie 
#       5      10      13 
# sapply(grps, function(x) sample(x$group, 1, prob=x$expected_probs))
#    Adam   Barry Charlie 
#      3       9      11 
0 голосов
/ 02 февраля 2020

Не решение tapply(), но вот решение с sample_n() из dplyr.

Переименование столбца probs в expected_probs:

name<-c(rep("Adam", times = 6), rep("Barry", times = 4), rep("Charlie", times = 5))
group<-c(1:15)
expected_probs<-c(0.4, 0.2, 0.1, 0.15, 0.1, 0.05, 0.25, 0.35, 0.3, 0.1, 0.2, 0.15, 0.30, 0.15, 0.2)
df<-data.frame(name, group, expected_probs)
library(dplyr)

df %>% 
  group_by(name) %>%
  sample_n(size = 1, weight = expected_probs)

# A tibble: 3 x 3
# Groups:   name [3]
  name    group expected_probs
  <fct>   <int>          <dbl>
1 Adam        4           0.15
2 Barry       9           0.3 
3 Charlie    12           0.15

Проверка соответствия наблюдаемых результатов ожидаемым вероятностям путем тиражирования выборки:

iterations <- 10000

results <- replicate(expr = df %>% 
                       group_by(name) %>%
                       sample_n(size = 1, weight = expected_probs),
                     n = iterations,
                     simplify = FALSE) %>% 
  bind_rows(.id = "iteration") %>% 
  group_by(name, group, expected_probs) %>% 
  summarize(observed_probs = n() / iterations)

results

# A tibble: 15 x 4
# Groups:   name, group [15]
   name    group expected_probs observed_probs
   <fct>   <int>          <dbl>          <dbl>
 1 Adam        1           0.4          0.391 
 2 Adam        2           0.2          0.198 
 3 Adam        3           0.1          0.102 
 4 Adam        4           0.15         0.154 
 5 Adam        5           0.1          0.104 
 6 Adam        6           0.05         0.0504
 7 Barry       7           0.25         0.252 
 8 Barry       8           0.35         0.346 
 9 Barry       9           0.3          0.297 
10 Barry      10           0.1          0.105 
11 Charlie    11           0.2          0.202 
12 Charlie    12           0.15         0.151 
13 Charlie    13           0.3          0.294 
14 Charlie    14           0.15         0.153 
15 Charlie    15           0.2          0.201 
...