J'ai une colonne de chaîne avec des virgules. Je souhaite convertir cette colonne unique en plusieurs colonnes étiquetées, avec des valeurs remplies de manière appropriée. La trame de données de sortie aurait 3 colonnes (A, B et C). La ligne 1 comprendrait les colonnes A et B remplies par «Oui» et C par «Non». La ligne 2 aurait les 3 colonnes remplies avec "Oui", etc.
A B C Yes Yes No Yes Yes Yes Yes No No Yes No Yes
Sortie requise
df1 <- data.frame(X= c("A, B", "A, B, C", "A", "A, C")) df1 X 1 A, B 2 A, B, C 3 A 4 A, C
N'importe quel indice, s'il vous plaît.
6 Réponses :
Quelque chose comme ceci:
library(tidyverse) df1 %>% mutate(id = row_number()) %>% separate_rows(X) %>% group_by(id) %>% mutate(Y = "yes") %>% spread(X, Y, fill = "no") # A tibble: 4 x 4 # Groups: id [4] id A B C <int> <chr> <chr> <chr> 1 1 yes yes no 2 2 yes yes yes 3 3 yes no no 4 4 yes no yes
Une approche légèrement différente qui ne repose pas sur le regroupement. La conversion finale en "Oui /" Non "est également effectuée par colonne, plutôt que de s'appuyer sur une conversion de données longues en données larges. Pour un très grand ensemble de données, cela peut être un peu plus efficace.
df2 <- df1 %>% mutate(row_num = 1:n()) %>% separate_rows(X) %>% spread(X, 1) %>% select(-row_num) %>% mutate_all(~ifelse(!is.na(.), 'Yes', 'No')) A B C 1 Yes Yes No 2 Yes Yes Yes 3 Yes No No 4 Yes No Yes
Utilisation de splitstackshape
library(splitstackshape) newdf=cSplit_e(df1, "X", sep = ", ",type = "character") newdf[newdf==1]='Yes' newdf[is.na(newdf)]='No' newdf X X_A X_B X_C 1 A, B Yes Yes No 2 A, B, C Yes Yes Yes 3 A Yes No No 4 A, C Yes No Yes
Voici une autre solution en base
lets <- strsplit(as.character(.subset2(df1,1L)), ', ') lets_unique <- unique(unlist(lets)) vapply(seq_along(lets_unique),function(k)grepl(lets_unique[k],lets),logical(length(lets))) # [,1] [,2] [,3] # [1,] TRUE TRUE FALSE # [2,] TRUE TRUE TRUE # [3,] TRUE FALSE FALSE # [4,] TRUE FALSE TRUE
Voici une option utilisant base R
avec table
. Nous divisons la colonne 'X' par ,
en une liste
de vecteurs
s, la convertissons en deux colonnes data.frame avec
stack
, obtenez la fréquence avec table
et convertissez-la en table(stack(setNames(strsplit(as.character(df1$X), ", +"),
seq_len(nrow(df1))))[2:1]) > 0
# values
#ind A B C
# 1 TRUE TRUE FALSE
# 2 TRUE TRUE TRUE
# 3 TRUE FALSE FALSE
# 4 TRUE FALSE TRUE
logique
Via stringi
stringi::stri_split_fixed(df1$X, ", ", simplify = TRUE) != "" # [,1] [,2] [,3] # [1,] TRUE TRUE FALSE # [2,] TRUE TRUE TRUE # [3,] TRUE FALSE FALSE # [4,] TRUE TRUE FALSE
TRUE
/ FALSE
est essentiellement oui
/ non
mais si vous avez besoin de la matrice de caractères, vous pouvez toujours faire ifelse (., "yes", "no")
et conserver la structure de la matrice.
Variables factices d'une variable chaîne