J'ai plusieurs dataframes qui ressemblent à ceci:
name var1 1 A cat,dog,worm 2 B dog,horse,bird,cat,lion 3 C eagle,fox,chick,giraffe
Je voudrais maintenant fusionner vars1 à 3 pour obtenir une liste concise sans doublons.
Donc, par exemple le bloc de données combiné devrait ressembler à:
df.1 <- data.frame(name = c("A", "B", "C"), var1 = c("cat,dog", "dog,horse,bird", "eagle,fox,chick")) df.2 <- data.frame(name = c("A", "B", "C"), var2 = c("cat,dog,worm", "dog,horse,bird", "giraffe")) df.3 <- data.frame(name = c("A", "B", "C"), var3 = c("cat,dog,worm", "dog,horse,bird,cat,lion", NA)) ## merged all <- df.1 %>% left_join(df.2) %>% left_join(df.3) > all name var1 var2 var3 1 A cat,dog cat,dog,worm cat,dog,worm 2 B dog,horse,bird dog,horse,bird dog,horse,bird,cat,lion 3 C eagle,fox,chick giraffe <NA>
paste
permettra de fusionner des chaînes séparées par des virgules, mais je ne sais pas comment supprimer les doublons?
Je voudrais faire cela en utilisant tidyverse et pas un autre paquet.
4 Réponses :
Utilisation de baseR
,
name var1 var2 var3 VAR 1 A cat,dog cat,dog,worm cat,dog,worm cat,dog,worm 2 B dog,horse,bird dog,horse,bird dog,horse,bird,cat,lion dog,horse,bird,cat,lion 3 C eagle,fox,chick giraffe <NA> eagle,fox,chick,giraffe
gives ,
all$VAR <- sapply(seq(nrow(all)),function(x) { k <- paste(unlist(all[x,2:4][,!is.na(all[x,2:4])]),collapse=",") paste(unique(unlist(strsplit(k,","))),collapse=",") })
C'est une solution entièrement tidyverse
, bien qu'un peu longue en code. Il peut sûrement être optimisé, mais il répond à votre question.
Pour une meilleure explication de toutes les étapes, je vous suggère de les exécuter une par une pour comprendre les opérations effectuées et comment le jeu de données change après chaque étape. P >
library(tidyverse) all %>% pivot_longer(starts_with("var"), names_to = "vars") %>% mutate(value = str_split(value, ",")) %>% unnest(value) %>% filter(!is.na(value)) %>% group_by(name) %>% distinct(value) %>% mutate(var = paste(value, collapse = ",")) %>% select(-value) %>% ungroup() %>% distinct() # A tibble: 3 x 2 # name var # <chr> <chr> # 1 A cat,dog,worm # 2 B dog,horse,bird,cat,lion # 3 C eagle,fox,chick,giraffe
Vous pouvez obtenir les données au format long, obtenir des valeurs dans différentes lignes, pour chaque nom
créer une valeur unique
non-NA séparée par des virgules.
all$var4 <- apply(all[-1], 1, function(x) toString(na.omit(unique(unlist(strsplit(x, ','))))))
En base R, nous pouvons utiliser apply
ligne par ligne:
library(dplyr) library(tidyr) all %>% pivot_longer(cols = var1:var3, names_to = 'col') %>% separate_rows(value) %>% group_by(name) %>% summarise(var1 = toString(na.omit(unique(value)))) # name var1 # <chr> <chr> #1 A cat, dog, worm #2 B dog, horse, bird, cat, lion #3 C eagle, fox, chick, giraffe
Voici une solution base R
:
Première étape: collez
les lignes ensemble, strsplit
, réduisez-les à uniques
valeurs, combinez toString
, et supprimez NA
:
new name var1 1 A cat, dog, worm 2 B dog, horse, bird, cat, lion 3 C eagle, fox, chick, giraffe
Deuxième étape: column-bind tous [1]
avec var1
new <- cbind(all[1], var1)
Résultat:
var1 <- gsub(", NA", "", unlist(as.character(lapply(sapply(strsplit(apply(all[2:4], 1, paste0, collapse = " "), " |,"), unique), toString))))
p >
Cela peut aider: stackoverflow.com/questions/35286596/... Collez simplement toutes les valeurs des colonnes en premier: stackoverflow.com/questions/14568662/...
est-il possible de faire ce découpage unique dans dplyr?
Il n'y a rien de spécial à déplyr pour le fractionnement. C'est purement une opération de chaîne. Vos données ne sont pas "rangées", donc ce n'est pas génial pour les verbes dplyr. Le package
stringr
est plus utile pour le fractionnement. Ou vous pouvez utiliser la fonctiontidyr :: separ_rows ()
pour rendre vos données plus ordonnées. Utilisez les valeurs non pas comme une chaîne séparée par des virgules, mais comme des valeurs de cellule appropriées.