Tidyr, reshape2 ou dplyr

Exemplo:

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 é:

    x   d   e   f
    a	1	0	0	
    b	0	0	1	
    c	0	1	0

Alguma sugestão?

(HELPPPPP)

Oi Fernanda!
Minha ideia com dplyr + tidyr:

# 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

Created on 2021-10-26 by the reprex package (v2.0.1)

1 curtida

Fernanda,

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

Created on 2021-10-26 by the reprex package (v2.0.1)

2 curtidas