Pergunta: Você pode realizar uma filtragem realmente confiável com base em um desenho dentro do filtro ou está fadado ao fracasso?
Objetivo: Dentro de dplyr::filter()
, remover linhas do tipo A (versicolor) se um sorteio aleatório falhar, e remover linhas do tipo B (virginica) se o sorteio for aprovado. Deve sempre terminar com 5 linhas aleatórias de dados setosa e 1 linha aleatória de virginica (1/8 de chance) ou versicolor (7/8 de chance).
Tentar:
as_tibble(iris) %>%
group_by(Species) %>%
mutate(draw = case_when(
Species == "setosa" ~ 5,
Species == "versicolor" ~ 1,
Species == "virginica" ~ 1
)) %>%
slice(sample(n(),draw[1])) %>%
filter(
if(round(runif(1),3) <= 1/8){ Species != "versicolor" }
else { Species != "virginica" }
)
Problema: embora isso normalmente funcione retornando apenas um ou outro, ocasionalmente obterei ambos ou nenhum. Por curiosidade, parece que consigo ambos 11% das vezes, nem 11% das vezes, e apenas um (o que está correto) apenas 78% das vezes.
Entendo que uma solução seria terminar o cano após o slice e depois desenhar dentro de uma if()
instrução:
data <- as_tibble(iris) %>%
group_by(Species) %>%
mutate(draw = case_when(
Species == "setosa" ~ 5,
Species == "versicolor" ~ 1,
Species == "virginica" ~ 1
)) %>%
slice(sample(n(),draw[1]))
if(round(runif(1),3) <= 1/8){
data %>%
filter(Species != "versicolor")
}
else {
data %>%
filter(Species != "virginica")
}
Porém, como percebi que é possível realizar o sorteio dentro do filtro, tenho interesse em saber se é prático.
Por que você não calcula a probabilidade antes?
Parece mais limpo do que
if ... else
no final.A razão pela qual às vezes ele não imprime nenhum ou ambos é porque você não extrai 1 número aleatório, mas 3! Um para cada grupo.
filter
no seu código está sendo aplicado tp a grouppeddata.frame
, então você obtém um número aleatório para cada grupo.Tente executar este código. Você verá que imprimirá 3 números.
Portanto, você poderia corrigir seu código simplesmente adicionando
ungroup
antesfilter
: