2010-07-17 24 views
7

Pregunta de rendimiento bastante básica de un novato R. Me gustaría asignar una ID de grupo a cada fila en un marco de datos mediante combinaciones únicas de campos. Aquí está mi enfoque actual:Asignación de ID de grupo con 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 

Aunque esto funciona bien para las tramas de datos con relativamente pocas filas o un pequeño número de grupos, me encuentro con problemas de rendimiento con conjuntos de datos grandes (> 100.000 filas) que tienen muchos grupos únicos.

¿Alguna sugerencia para mejorar la velocidad de esta tarea? Posiblemente con experimental de plyr idata.frame()? ¿O estoy haciendo esto mal?

Gracias de antemano por su ayuda.

Respuesta

14

Trate de usar la función id (también en plyr):

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

Actualización:

Se considera que la función de id obsoleto desde la versión dplyr 0.5.0. La función group_indices proporciona la misma funcionalidad.

+0

Aparentemente tengo que volver atrás y leer la documentación de plyr con más cuidado, esto es exactamente lo que estaba buscando. Evalué esta solución y JoFrhwld en mi conjunto de datos de prueba: un marco de datos con 164,961 observaciones y 91,876 grupos únicos basados ​​en 3 variables de agrupamiento. Usé cada uno de estos métodos para asignar una variable de identificación de grupo 100 veces. El tiempo medio transcurrido para id() fue de .958 (sd .0310). El tiempo medio transcurrido para pegar los campos de agrupación fue 1.94 (sd. 0946). ¡Gracias a ambos! – danpelota

2

¿Es necesario que la ID sea una cadena aleatoria de 10 caracteres? Si no, ¿por qué no simplemente pegar juntas las columnas del marco de datos? Si los ID deben tener la misma longitud en caracteres, convertir a factores numéricos, a continuación, pegarlos juntos:

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

Entonces, si usted realmente necesita tener 10 ID de carácter, me genero sólo el número n de ID y cambiar el nombre de los niveles de identificación con ellos

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 

también, como un aparte, que no es necesario utilizar function(x) con ddply esa manera con transform(). Este código funcionaría de la misma manera:

ddply(df, c("st.num", "st.name"), transform, household=getString()) 
Cuestiones relacionadas