2010-07-17 4 views
7

Question de performance assez basique d'un débutant R. Je voudrais attribuer un ID de groupe à chaque ligne dans un bloc de données par des combinaisons uniques de champs. Voici mon approche actuelle:Attribution d'un ID de groupe avec ddply

> # An example data frame 
> df <- data.frame(name=c("Anne", "Bob", "Chris", "Dan", "Erin"), 
        st.num=c("101", "102", "105", "102", "150"), 
        st.name=c("Main", "Elm", "Park", "Elm", "Main")) 
> df 
    name st.num st.name 
1 Anne 101 Main 
2 Bob 102  Elm 
3 Chris 105 Park 
4 Dan 102  Elm 
5 Erin 150 Main 
> 
> # A function to generate a random string 
> getString <- function(size=10) return(paste(sample(c(0:9, LETTERS, letters), size, replace=TRUE), collapse='')) 
> 
> # Assign a random string for each unique street number + street name combination 
> df <- ddply(df, 
       c("st.num", "st.name"), 
       function(x) transform(x, household=getString())) 
> df 
    name st.num st.name household 
1 Anne 101 Main 1EZWm4BQel 
2 Bob 102  Elm xNaeuo50NS 
3 Dan 102  Elm xNaeuo50NS 
4 Chris 105 Park Ju1NZfWlva 
5 Erin 150 Main G2gKAMZ1cU 

Bien que cela fonctionne bien pour les trames de données avec peu de lignes ou un petit nombre de groupes, je rencontre des problèmes de performance avec des ensembles de données plus importants (> 100.000 lignes) qui ont de nombreux groupes uniques.

Des suggestions pour améliorer la vitesse de cette tâche? Peut-être avec idata.frame expérimental de plyr()? Ou je vais à ce sujet tout faux?

Merci d'avance pour votre aide.

Répondre

14

Essayez d'utiliser la fonction id (également plyr):

df$id <- id(df[c("st.num", "st.name")], drop = TRUE) 

Mise à jour:

La fonction id est considérée comme obsolète depuis la version de dplyr 0.5.0. La fonction group_indices offre la même fonctionnalité.

+0

Apparemment, je dois revenir en arrière et lire la documentation de plyr plus attentivement - c'est exactement ce que je cherchais. J'ai évalué cette solution et JoFrhwld sur mon ensemble de données de test: un cadre de données avec 164 961 observations et 91 876 groupes uniques basés sur 3 variables de regroupement. J'ai utilisé chacune de ces méthodes pour attribuer une variable d'ID de groupe 100 fois. Le temps moyen écoulé pour id() était .958 (sd .0310). Le temps moyen écoulé pour coller les champs de regroupement était de 1,94 (écart-type 0946). Merci à tous les deux! – danpelota

2

Est-il nécessaire que l'ID soit une chaîne aléatoire de 10 caractères? Si non, pourquoi ne pas simplement coller les colonnes de la trame de données. Si les ID doivent être de la même longueur en caractères, convertir des facteurs à numérique, puis les coller ensemble:

df$ID <- paste(as.numeric(df$st.num), as.numeric(df$st.name), sep = "") 

Ensuite, si vous avez vraiment besoin d'avoir 10 ID de caractère, je produis seulement le nombre n d'ID et renommer les niveaux d'identité avec eux

df$ID <- as.factor(df$ID) 
n <- nlevels(df$ID) 

getID <- function(n, size=10){ 
    out <- {} 
    for(i in 1:n){ 
    out <- c(paste(sample(c(0:9, LETTERS, letters), size, replace=TRUE), collapse='')) 
    } 
    return(out) 
} 

newLevels <- getID(n = n) 

levels(df$ID) <- newLevels 

aussi, en aparté, vous n'avez pas besoin d'utiliser function(x) avec ddply cette façon avec transform(). Ce code fonctionnerait exactement la même chose:

ddply(df, c("st.num", "st.name"), transform, household=getString()) 
Questions connexes