1
votes

Valeurs de groupe basées sur le vecteur et la colonne de mise à jour

J'essaie de regrouper diverses valeurs en fonction d'un vecteur prédéfini, puis de mettre à jour une colonne.

Exemples de données

ID           Type         Grouping
1  1        Windows          IT
2  2 Windows Server          IT
3  3            Cat        Animal
4  4            Dog        Animal
5  5           Eggs        Food

Ce que j'ai essayé mais échoué

df %>% mutate(Grouping = ifelse(Type == "Windows", "IT", 
                                ifelse ...))


3 commentaires

Créer un dataframe et fusionner?


Votre gsub échoue car vous fournissez un vecteur comme expression de recherche. Cela fonctionnera si vous faites: gsub (paste (it, collapse = "|"), "IT", c ("Windows", "Windows Server", "Cat", "Dog", "Eggs") )


@PavoDive c'est vraiment utile, merci!


3 Réponses :


0
votes

Une option serait de créer une liste (ou un data.frame ) pour les mappages, puis de faire une left_join

map <- list(
    it = c("Windows", "Windows Server"),
    animal = c("Cat", "Dog"),
    food = c("Eggs"))

library(dplyr)   
df %>% left_join(stack(map), by = c("Type" = "values"))
#  ID           Type    ind
#1  1        Windows     it
#2  2 Windows Server     it
#3  3            Cat animal
#4  4            Dog animal
#5  5           Eggs   food


3 commentaires

Merci pour la solution, cela fonctionne parfaitement! Cependant j'ai une question. Savez-vous pourquoi lorsque je définis mes vecteurs en dehors de la liste, la pile (carte) ne semble pas fonctionner? Il me montre cette erreur: Erreur dans data.frame (values ​​= unlist (unname (x)), ind, stringsAsFactors = FALSE): les arguments impliquent un nombre de lignes différent: 5, 0


@Javier "Savez-vous pourquoi lorsque je définis mes vecteurs en dehors de la liste, la stack (map) ne semble pas fonctionner?" Je ne sais pas ce que cela moyens? Pourquoi "en dehors de la liste "? Vous devez définir une liste avec des éléments nommés. stack puis rangée les entrées de chaque élément list dans la colonne values ​​ puis ajoute une colonne ind pour indiquer de quel élément ils sont venus.


Ah, je ne savais pas que la liste devait avoir des éléments nommés pour que stack fonctionne. Merci beaucoup!



1
votes

Créez une liste de vos vecteurs prédéfinis, puis vérifiez quel élément de la liste contient les éléments dans le df$Type

mylist = mget(c("animal", "food", "it"))
names(mylist)[max.col(t(sapply(df$Type, function(x) lapply(mylist, function(y) x %in% y))))]
#[1] "it"     "it"     "animal" "animal" "food"


0 commentaires

0
votes

la question telle que publiée n'a pas beaucoup de sens. Plus précisément, avec les exemples de données, il n'est pas plus simple de stocker les vecteurs de type indépendants que de stocker le type en tant qu'attribut de la trame de données initiale. peut-être pourriez-vous ajouter une couleur qui donne plus de détails sur la nature du problème.

Cela dit, en supposant que votre problème est que les vecteurs de recherche sont stockés dans une source différente et doivent être chargés indépendamment, une simple boucle devrait suffire . (J'utilise data.table, car je ne me souviens même plus comment utiliser un data.frame brut):

df <- data.table(ID = 1:5, Type = c("Windows", "Windows Server", "Cat", "Dog", "Eggs"))
it <- c("Windows", "Windows Server")
animal <- c("Cat", "Dog")
food <- c("Eggs")

lookup.names <- c("it", "animal", "food")
for (z in 1:length(lookup.names) ) {
    lookup <- get(lookup.names[z]) #maybe need to do some more sophisticated load, like from a file or database
    df[Type %in% lookup, Grouping := lookup.names[z]]
}


1 commentaires

Bonjour, la question posée est un exemple édulcoré et reproductible de mon problème. Une boucle n'est peut-être pas aussi efficace que j'ai affaire à un ensemble de données volumineuses; donc utiliser un left_join tel que fourni par les autres utilisateurs fonctionne mieux