x <- c("a", "a", "b", "c", "c")
y <- c("d", "d", "f", "e", "e")
num <- c(10, 20, 21,19, 45)
data <- data.frame(cbind(x,y,num))
data
x y num
a d 10
a d 20
b f 21
c e 19
c e 45
Utilizando dcast de reshape2, tenho:
m <- dcast(data, x ~ y,
value.var = "num",
fun.aggregate = length)
m
x d e f
a 2 0 0
b 0 0 1
c 0 2 0
Ele faz o que eu preciso na ideia de linhas se tornarem colunas, mas não quero que as frequências de a em d e c em e sejam 2, quero que seja 1. A fun.aggregate = length não é a ideal e não encontrei outras.
Tentei pelas funções pivot_wider, dummy_cols e fazer com manipulação do dplyr e não consegui o resultado experado que é:
# CÓDIGO ORIGINAL DA FERNANDA -------
x <- c("a", "a", "b", "c", "c")
y <- c("d", "d", "f", "e", "e")
num <- c(10, 20, 21,19, 45)
data <- data.frame(cbind(x,y,num))
data
#> x y num
#> 1 a d 10
#> 2 a d 20
#> 3 b f 21
#> 4 c e 19
#> 5 c e 45
# A PARTIR DAQUI A BIA EDITANDO ------
library(magrittr)
data %>%
# deixar em formato largo/wide, usando a coluna y
tidyr::pivot_wider(names_from = y, values_from = num, values_fn = length) %>%
# fazer um case_when das colunas d até e,
# quando for NA, receber 0
# quando for algum número, receber 1
dplyr::mutate(dplyr::across(.cols = d:e,
.fns = ~dplyr::case_when(
is.na(.) ~ 0,
TRUE ~ 1))) %>%
# reorganiza as colunas para ficar exatamente como a prova real
dplyr::relocate(e, .before = f)
#> # A tibble: 3 × 4
#> x d e f
#> <chr> <dbl> <dbl> <dbl>
#> 1 a 1 0 0
#> 2 b 0 0 1
#> 3 c 0 1 0
Seguindo a sugestão da @beatrizmilz e tentando colocar tudo em uma função só. Fica um pouco mais compacto, mas a lógica é parecida (ou seja, retornar 1 sempre que houver elementos e 0 caso contrário):
library(magrittr)
# Tabela exemplo
data <- data.frame(
x = c("a", "a", "b", "c", "c"),
y = c("d", "d", "f", "e", "e"),
num = c(10, 20, 21,19, 45)
)
data
#> x y num
#> 1 a d 10
#> 2 a d 20
#> 3 b f 21
#> 4 c e 19
#> 5 c e 45
# Função simples que retorna 1
fn <- function(x) 1
# Fazer o pivot
data %>%
tidyr::pivot_wider(
names_from = y, # Nomes das colunas virão de `y`
values_from = num, # Valores das linhas virão de `num`
names_sort = TRUE, # Ordenar as novas colunas por nome
values_fill = 0, # Preencher as casas vazias com 0
values_fn = fn # Preencher com 1 o resto das casas
)
#> # A tibble: 3 × 4
#> x d e f
#> <chr> <dbl> <dbl> <dbl>
#> 1 a 1 0 0
#> 2 b 0 0 1
#> 3 c 0 1 0
# Função que retorna 0 para casas vazias e 1 para o resto
fn2 <- function(x) min(1, length(x))
# Se preferir com `dcast()` (não recomendo)
reshape2::dcast(
data, x ~ y,
value.var = "num",
fun.aggregate = fn2
)
#> x d e f
#> 1 a 1 0 0
#> 2 b 0 0 1
#> 3 c 0 1 0