Пошаговая выборка в стакане - PullRequest
3 голосов
/ 02 июля 2019

Я пытаюсь смоделировать некоторые данные путем выборки из нескольких шагов.

Первый шаг (создать х) работает нормально.

На втором шаге я хочу создать переменную y путем выборки из разных векторов на основе значения x.

Мой код выполняется без ошибок, но терпит неудачу при том, чего я пытаюсь достичь, так как он выбирает только одно значение, например, x == «A», а затем повторно использует это значение для всех последующих строк, где x == «A» , Я хочу, чтобы он пробовал один раз для каждой строки, где x == "A"

Код:

library(tidyverse)
set.seed(1)

data <- tibble(
  x = sample(c("A", "B", "C"), size = 10000, prob = c(0.1, 0.2, 0.7), replace = TRUE),
  y = case_when(
    x == "A" ~ sample(c("A1", "A2", "A3"), size = 1, prob = c(0.3, 0.4, 0.3)),
    x == "B" ~ sample(c("B1", "B2", "B3"), size = 1, prob = c(0.3, 0.4, 0.3)),
    x == "C" ~ sample(c("C1", "C2", "C3"), size = 1, prob = c(0.3, 0.4, 0.3)),
  ))

unique(data$x)
[1] "C" "A" "B"

unique(data$y)
[1] "C1" "A2" "B3"

Если код работает как задумано, unique(data$y) должен вернуть что-то похожее на [1] "A1", "A2", "A3", "B1", "B2", "B3", "C1", "C2", "C3"

Я знаю, что проблема в аргументе size = 1 в sample (), но чем я могу его заменить? Удаление его возвращает ошибку:

Error: `x == "A" ~ sample(c("A1", "A2", "A3"), prob = c(0.3, 0.4, 0.3))` must be length 100 or one, not 3

И я пробовал size = nrow(.data) и size=nrow(.), но это также возвращает ошибку.

Есть ли простое решение для этого?

Ответы [ 3 ]

2 голосов
/ 02 июля 2019

Возможно, есть более простой способ, но он остается близким к исходному коду и работает ...

data <- tibble(
  x = sample(c("A", "B", "C"), size = 10000, prob = c(0.1, 0.2, 0.7), replace = TRUE)) %>%
  rowwise() %>%
  summarise(x= x, 
            y = case_when(
    x == "A" ~ sample(c("A1", "A2", "A3"), size = 1, prob = c(0.3, 0.4, 0.3)),
    x == "B" ~ sample(c("B1", "B2", "B3"), size = 1, prob = c(0.3, 0.4, 0.3)),
    x == "C" ~ sample(c("C1", "C2", "C3"), size = 1, prob = c(0.3, 0.4, 0.3)),
  ))
1 голос
/ 02 июля 2019

Было бы просто понять, если бы вы поделили это на шаги

library(dplyr)
data <- tibble(
   x = sample(c("A", "B", "C"), size = 10000, 
                prob = c(0.1, 0.2, 0.7), replace = TRUE))

data <- data %>%
  mutate(y = case_when(
     x == "A" ~ sample(c("A1", "A2", "A3"), size = n(), 
               prob = c(0.3, 0.4, 0.3), replace = TRUE),
     x == "B" ~ sample(c("B1", "B2", "B3"), size = n(), 
                 prob = c(0.3, 0.4, 0.3), replace = TRUE),
     x == "C" ~ sample(c("C1", "C2", "C3"), size = n(), 
                prob = c(0.3, 0.4, 0.3), replace = TRUE),
)) 

unique(data$y)
#[1] "C2" "B3" "A1" "C3" "B1" "C1" "B2" "A3" "A2"

Или, если вы хотите продолжить свой путь, вам нужно указать аргумент size, такой же, как упомянутый для x с replace = TRUE

data <- tibble(
  x = sample(c("A", "B", "C"), size = 10000, 
            prob = c(0.1, 0.2, 0.7), replace = TRUE),
  y = case_when(
    x == "A" ~ sample(c("A1", "A2", "A3"), size = 10000, 
                  prob = c(0.3, 0.4, 0.3), replace = TRUE),
    x == "B" ~ sample(c("B1", "B2", "B3"), size = 10000, 
                  prob = c(0.3, 0.4, 0.3), replace = TRUE),
    x == "C" ~ sample(c("C1", "C2", "C3"), size = 10000, 
                  prob = c(0.3, 0.4, 0.3), replace = TRUE),
  ))
1 голос
/ 02 июля 2019

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

v1 <- c('A', 'A', 'B', 'B', 'C', 'C', 'C', 'A', 'A')

#Vectorized ifelse
ifelse(v1 == 'A', sample(c("A1", "A2", "A3"), size = 1, prob = c(0.3, 0.4, 0.3)), NA)
#[1] "A3" "A3" NA   NA   NA   NA   NA   "A3" "A3"

#Not vectorized if/else with a loop,
sapply(v1, function(i) if (i == 'A') { sample(c("A1", "A2", "A3"), size = 1, prob = c(0.3, 0.4, 0.3)) }else {NA})
#   A    A    B    B    C    C    C    A    A 
#"A2" "A3"   NA   NA   NA   NA   NA "A2" "A1" 
...