2010-02-09 16 views
43

nota: esta pregunta y las siguientes respuestas se refieren a las versiones data.table < 1.5.3; v. 1.5.3 fue lanzado en febrero de 2011 para resolver este problema. ver más reciente tratamiento (03-2012): Translating SQL joins on foreign keys to R data.table syntaxCómo hacer una operación de fusión de data.table


que he estado cavando a través de la documentación de la data.table package (un reemplazo para hoja.de.datos que es mucho más eficiente para ciertas operaciones), incluyendo Josh Reich's presentation on SQL and data.table at the NYC R Meetup (pdf), pero no puede entender esta operación totalmente trivial.

> x <- DT(a=1:3, b=2:4, key='a') 
> x 
    a b 
[1,] 1 2 
[2,] 2 3 
[3,] 3 4 
> y <- DT(a=1:3, c=c('a','b','c'), key='a') 
> y 
    a c 
[1,] 1 a 
[2,] 2 b 
[3,] 3 c 
> x[y] 
    a b 
[1,] 1 2 
[2,] 2 3 
[3,] 3 4 
> merge(x,y) 
    a b c 
1 1 2 a 
2 2 3 b 
3 3 4 c 

Los documentos dicen "Cuando [el primer argumento] es en sí mismo un data.table, una unión que se invoca similar a basar :: fusión, pero utiliza búsqueda binaria en la tecla ordenada." Claramente este no es el caso. ¿Puedo obtener las otras columnas de y en el resultado de x [y] con data.tables? Parece que solo está tomando las filas de x donde la clave coincide con la clave de y, pero ignorando completamente el resto de ...

+2

Esto fue resuelto por v1.5.3 lanzado a CRAN en febrero de 2011. Consulte las NOTICIAS, las nuevas preguntas frecuentes sobre "data.table" y las "corregidas". –

Respuesta

27

Usted está citando la parte incorrecta de la documentación. Si usted tiene una mirada en el documento de [.data.table se lee:

Cuando i es un data.table, x debe tener una clave , lo que significa unirse I a X y retorno las filas de X que coincidan. Se realiza una unión equitativa entre cada columna en i a cada columna en la clave de x en orden. Esto es similar a la base R funcionalidad de subconjuntos de una matriz por una matriz 2-columna, y en mayores dimensiones subconjuntos un matriz n-dimensional por una matriz n-columna

I admiten la La descripción del paquete (la parte que citó) es algo confusa, porque parece decir que se puede usar la operación "[" en lugar de fusionar. Pero creo que lo que dice es: si xey son ambos data.tables usamos un join en un índice (que se invoca como merge) en lugar de la búsqueda binaria.


Una cosa más:

La biblioteca data.table he instalado a través de install.packages faltaba la merge.data.table method, así que usar merge llamaría merge.data.frame. Después de instalar el package from R-Forge R utilizó el método más rápido merge.data.table.

Puede comprobar si tiene el método merge.data.table marcando la salida de:

methods(generic.function="merge") 

EDITAR [respuesta ya no es válida]: esta pregunta se refiere a data.table versión 1.3. En la versión 1.5.3, el comportamiento de data.table cambió yx [y] devuelve los resultados esperados. Gracias Matthew Dowle, autor de data.table, para señalar esto en los comentarios.

+0

Ah. Parece que la versión de CRAN es la versión 1.2, mientras que la versión de R-Forge es la versión 1.3. El método 'merge' fue aparentemente agregado en 1.3. Por lo que puedo decir mirando alrededor de R-Forge, el método fue agregado hace algo así como 8 meses atrás, ¡así que no sé por qué aún no está en CRAN! – Harlan

+5

La sintaxis de X [Y] se modificó en v1.5.3 y se lanzó a CRAN en febrero de 2011. Consulte las NOTICIAS, las nuevas preguntas frecuentes sobre datos y las preguntas corregidas. –

3

Creo que f3lix es correcto y que la documentación es un poco engañosa. El beneficio está en hacer una unión rápida para subconjuntos de los datos.Finalmente, necesitará utilizar la función merge después como en el ejemplo anterior.

Verá en Josh's presentation on using data.table que así es como se ejecuta su ejemplo. Primero subconjuntos uno de los data.tables, luego hace una fusión:

library(data.table) 
sdt <- DT(series, key='series_id') 
ddt <- DT(data, key='series_id') 
u <- sdt[ grepl('^[A-Z]{2}URN', fred_id) & !grepl('DSURN', fred_id) ] 
d <- ddt[ u, DT(min=min(value)), by='series_id', mult='all'] 
data <- merge(d,series)[,c('title','min','mean','max')] 
+0

Gracias, Shane. Estaba muy confundido por esto, ya que sabía (o creía saber) que 'merge' no aprovecharía las ventajas de' data.table'. – Harlan

14

Gracias por las respuestas. Me perdí este hilo cuando fue publicado originalmente. data.table ha cambiado desde febrero. 1.4.1 fue lanzado a CRAN hace un tiempo y 1.5 sale pronto. Por ejemplo, el alias DT() ha sido reemplazado por list(); como una primitiva es mucho más rápida, y data.table ahora hereda de data.frame por lo que funciona con paquetes que solo aceptan data.frame como ggplot y reticulado, sin ninguna conversión requerida (más rápido y más conveniente).

¿Es posible suscribirse a la etiqueta data.table para recibir un correo electrónico cuando alguien publique una pregunta con esa etiqueta? La lista de ayuda de tabla de datos ha crecido a unos 30-40 mensajes al mes, pero me complace responder aquí también si puedo recibir algún tipo de notificación.

Mateo

+1

Hola, gracias por la nota! Sí, definitivamente es posible. Haga clic en el cuadro de etiqueta 'data.table' en la esquina superior derecha de la pantalla, luego desplácese hasta la parte inferior hasta que vea el ícono RSS, y úselo para suscribirse a las preguntas con esta etiqueta. – Harlan

+0

Gracias Harlan. Me suscribí ahora. –

9

Creo que el uso de la función base::merge no se necesita, como el uso de data.table se une puede ser mucho más rápido. P.ej. mira lo siguiente. Hago x y y data.tables con 3-3 columnas:

> x <- data.table(foo = 1:5, a=20:24, zoo = 5:1) 
> y <- data.table(foo = 1:5, b=30:34, boo = 10:14) 
> setkey(x, foo) 
> setkey(y, foo) 

y combinar tanto con base:merge y data.table se une a ver la velocidad de ejecuciones:

> system.time(merge(x,y)) 
    user system elapsed 
    0.027 0.000 0.023 
> system.time(x[,list(y,x)]) 
    user system elapsed 
    0.003 0.000 0.006 

Los resultados no son idénticos, como se este último tiene una columna adicional:

> merge(x,y) 
    foo a zoo b boo 
[1,] 1 20 5 30 10 
[2,] 2 21 4 31 11 
[3,] 3 22 3 32 12 
[4,] 4 23 2 33 13 
[5,] 5 24 1 34 14 
> x[,list(x,y)] 
    foo a zoo foo.1 b boo 
[1,] 1 20 5  1 30 10 
[2,] 2 21 4  2 31 11 
[3,] 3 22 3  3 32 12 
[4,] 4 23 2  4 33 13 
[5,] 5 24 1  5 34 14 

que no se podía hacer un gran problema :)

+3

Gracias, eso es interesante. Sin embargo, ¡una sintaxis totalmente desconocida! Si tuviera que usar eso, podría redefinir una función que no funciona '(x, y) x [, list (x, y)]' o algo así, tal vez soltando esa columna de clave extra también ... – Harlan

+2

Creo que el correcto la sintaxis para las uniones en data.table es en realidad x [y] o x [y,], es decir, las uniones deben usar el primer índice. Esto da los mismos resultados que merge. tenga en cuenta que x [y] e y [x] no necesitan ser idénticos, es decir, si y contiene entradas en foo que no son representativas de x. Tal vez me he perdido algo, pero vea Joins en el data.table [vignette] (http://cran.r-project.org/web/packages/data.table/vignettes/datatable-intro.pdf) – cboettig

+1

the above x [, list (x, y)] no funcionó para mí. Intenté x [, c (x, y)] y funcionó. Aunque no estoy seguro de si tiene sentido. – bala

Cuestiones relacionadas