web-dev-qa-db-fra.com

Agrégation par identifiant unique et concaténation des valeurs associées dans une chaîne

J'ai un besoin qui, j'imagine, pourrait être satisfait par aggregate ou reshape, mais je n'arrive pas à comprendre.

J'ai une liste de noms (brand) et le numéro d'identification qui l'accompagne (id). Ces données sont sous forme longue, donc les noms peuvent avoir plusieurs identifiants. Je voudrais dédupliquer par le nom (brand) et concaténer les multiples id possibles dans une chaîne séparée par un commentaire.

Par exemple:

brand            id 
RadioShack       2308
Rag & Bone       4466
Ragu             1830
Ragu             4518
Ralph Lauren     1638
Ralph Lauren     2719
Ralph Lauren     2720
Ralph Lauren     2721
Ralph Lauren     2722 

devrait devenir:

RadioShack       2308
Rag & Bone       4466
Ragu             1830,4518
Ralph Lauren     1638,2719,2720,2721,2722

Comment pourrais-je accomplir cela?

51
roody

Appelons votre data.frame DF

> aggregate(id ~ brand, data = DF, c)
         brand                           id
1   RadioShack                         2308
2   Rag & Bone                         4466
3         Ragu                   1830, 4518
4 Ralph Lauren 1638, 2719, 2720, 2721, 2722

Une autre alternative utilisant aggregate est:

result <- aggregate(id ~ brand, data = DF, paste, collapse = ",")

Cela produit le même résultat et maintenant id n'est plus un list. Merci au commentaire @Frank. Pour voir le class de chaque colonne, essayez:

> sapply(result, class)
      brand          id 
   "factor" "character"

Comme mentionné par @DavidArenburg dans les commentaires, une autre alternative utilise la fonction toString:

aggregate(id ~ brand, data = DF, toString)
59
Jilber Urbina

Une belle ligne propre dans data.table

library(data.table)
setDT(DF)

DEUX OPTIONS:

résultats sous forme de liste

DF[ , .(id = list(id)), by = brand]
          brand                       id
1:   RadioShack                     2308
2:   Rag & Bone                     4466
3:         Ragu                1830,4518
4: Ralph Lauren 1638,2719,2720,2721,2722
> 

résultats sous forme de chaîne

DF[ , .(id = paste(id, collapse=",")), by = brand]
          brand                       id
1:   RadioShack                     2308
2:   Rag & Bone                     4466
3:         Ragu                1830,4518
4: Ralph Lauren 1638,2719,2720,2721,2722

Remarque

Même si les deux résultats apparaissent identiques (c'est-à-dire lorsque vous les imprimez, ils ont l'air identiques), ils sont en fait très différents et permettre différentes fonctionnalités.

À savoir, l'utilisation de l'option de liste (la première) vous permet ensuite d'effectuer des fonctions sur l'orignal ids.

Ce dernier vous permettra d'afficher les informations plus facilement (y compris l'exportation vers CSV ou Excel), mais pour opérer sur les id, il faudra les épisser.

37
Ricardo Saporta

Ou en utilisant dplyr :

library(dplyr)
DF %>%
  group_by(brand) %>%
  summarise(id = paste(id, collapse = ","))

DF est le nom de votre data.frame.

22
Sam Firke

Voici les informations de la base R:

myby <- by(df$id,df$brand,function(x)paste(x,collapse=","))

Le formatage des objets "by" est bizarre. Vous pouvez prendre data.frame(id=c(myby)) et les marques deviendront des noms de domaine:

#                                    id
# RadioShack                       2308
# Rag & Bone                       4466
# Ragu                        1830,4518
# Ralph Lauren 1638,2719,2720,2721,2722

Alternativement, si vous chargez le package data.table, Cela fonctionnera:

dt <- data.table(df)
dt[,paste(id,collapse=","),by=brand]
#           brand                       V1
# 1:   RadioShack                     2308
# 2:   Rag & Bone                     4466
# 3:         Ragu                1830,4518
# 4: Ralph Lauren 1638,2719,2720,2721,2722
10
Frank