3 votes

Comment diviser le contenu des cellules en plusieurs colonnes pour créer des données larges?

J'ai un ensemble de données, les données proviennent d'une question à choix multiples dans un formulaire Google. Cependant, lors de l'exportation des données, toutes les options sélectionnées par les répondants sont mises dans une seule colonne, séparées par des virgules. Comme ceci.

df <- structure(list(teacher = c("Mary", "Andrew", "Rose", 
"Julia", "Richard"), grades = c("K, 1, 2, 3, 4", "1, 3, 4", "1, 2, 3, 4, 5", "4, 5", 
"K, 1, 2, 3, 4, 5")), 
class = "data.frame", row.names = c(NA, -5L))

J'aimerais séparer le contenu des cellules en plusieurs colonnes pour créer des données larges, de sorte que le tableau final ressemble à ceci :

df.wide <- structure(list(teacher = c("Mary", "Andrew", "Rose", 
"Julia", "Richard"), grade_k = c(1,0,0,0,1), grade_1 = c(1,1,1,0,1), grade_2 = 
c(1,0,1,0,1), grade_3 = c(1,1,1,0,1), grade_4 = c(1,1,1,1,1), grade_5 = c(0,0,1,1,1)), 
class = "data.frame", row.names = c(NA, -5L))

Comment puis-je faire cela en R. Merci d'avance pour toute aide

0voto

U9-Forward Points 8640

Essayez fastDummies::dummy_cols:

library(fastDummies)
x <- dummy_cols(df, selected_columns=c('grades'))
colnames(x) <- paste0("grade_", colnames(x))
cbind(df[1], x)

Sortie :

  teacher grade_1 grade_2 grade_3 grade_4 grade_5 grade_K
1    Mary       1       1       1       1       0       1
2  Andrew       1       0       1       1       0       0
3    Rose       1       1       1       1       1       0
4   Julia       0       0       0       1       1       0
5 Richard       1       1       1       1       1       1

0voto

LMc Points 725

Voici une option en utilisant tidyr:

library(tidyr)
library(stringr)

ncols <- max(sapply(df$grades, \(x) str_count(x, ","))) + 1

separate(df, grades, into = paste0("col", seq(ncols)), sep = ", ") %>% 
  pivot_longer(cols = -teacher) %>% 
  drop_na() %>% 
  pivot_wider(id_cols = teacher, 
              names_from = value,
              names_prefix = "grade_",
              values_fn  = \(x) as.numeric(length(list(x)) > 0),
              values_fill = 0)

Résultat

  teacher grade_K grade_1 grade_2 grade_3 grade_4 grade_5

1 Mary          1       1       1       1       1       0
2 Andrew        0       1       0       1       1       0
3 Rose          0       1       1       1       1       1
4 Julia         0       0       0       0       1       1
5 Richard       1       1       1       1       1       1

-1voto

akrun Points 148302

Une option plus facile est avec mtabulate de qdapTools après avoir scindé au ,

library(qdapTools)
out <- +(mtabulate(strsplit(df$grades, ",\\s+")) > 0)
colnames(out) <- paste0("grade_", colnames(out))
cbind(df[1], out)

-output

  teacher grade_1 grade_2 grade_3 grade_4 grade_5 grade_K
1    Mary       1       1       1       1       0       1
2  Andrew       1       0       1       1       0       0
3    Rose       1       1       1       1       1       0
4   Julia       0       0       0       1       1       0
5 Richard       1       1       1       1       1       1

Ou utilisez splitstackshape

library(splitstackshape)
cSplit_e(df, "grades", sep = ",", type = "character", fill = 0, drop = TRUE)
  teacher grades_1 grades_2 grades_3 grades_4 grades_5 grades_K
1    Mary        1        1        1        1        0        1
2  Andrew        1        0        1        1        0        0
3    Rose        1        1        1        1        1        0
4   Julia        0        0        0        1        1        0
5 Richard        1        1        1        1        1        1

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X