2012-03-28 14 views
16

El paquete data.table proporciona muchos de los mismos métodos de manejo de tabla que SQL. Si una tabla tiene una clave, esa clave consta de una o más columnas. Pero una tabla no puede tener más de una clave, porque no se puede ordenar de dos formas diferentes al mismo tiempo.Traducir uniones de SQL en claves externas a R sintaxis data.table

En este ejemplo, X y Y son data.table s con una sola columna de clave "id"; Y también tiene una columna sin clave "x_id".

X <- data.table(id = 1:5, a=4:8,key="id") 
    Y <- data.table(id = c(1,1, 3,5,7), x_id=c(1,4:1), key="id") 

La siguiente sintaxis se uniría a las tablas en sus claves:

X[Y] 

Como puedo traducir la siguiente sintaxis SQL para data.table código?

select * from X join Y on X.id = Y.x_id; 

Lo más cerca que he conseguido es:

Y[X,list(id, x_id),by = x_id,nomatch=0] 

Sin embargo, esto no hace unirse a la misma interno como la instrucción SQL.


Aquí es un ejemplo más claro en el que se y_id la clave externa, y queremos que la unión a buscar valores de Y2, donde X2$y_id = Y2$id.

X2 <- data.table(id = 1:5, y_id = c(1,1,2,2,2), key="id") 
    Y2 <- data.table(id = 1:5, b = letters[1:5], key="id") 

me gustaría producir la tabla:

id y_id b 
    1  1 "a" 
    2  1 "a" 
    3  2 "b" 
    4  2 "b" 
    5  2 "b" 

similar a lo que se hace por la siguiente kludge:

> merge(data.frame(X2), data.frame(Y2), by.x = "y_id", by.y = "id") 
    y_id id b 
1 1 1 a 
2 1 2 a 
3 2 3 b 
4 2 4 b 
5 2 5 b 

Sin embargo, cuando hago esto:

X2[Y2, 1:2,by = y_id] 

No obtengo el resultado deseado:

y_id V1 
[1,] 1 1 
[2,] 1 2 
[3,] 2 1 
[4,] 2 2 
+2

Puede cambiar temporalmente 'teclas X2' y los puso a' "y_id" '; luego realice una unión normal 'Y2 [X2]' (o 'X2 [Y2]' dependiendo de la dirección) y luego restaure la clave anterior de 'X2'. – digEmAll

+0

@digEmAll que es útil, pensé que era lo que hace el argumento 'by' ... pero ¿se puede aplicar esto a una combinación de tabla múltiple (> 2) donde la tabla de destino (izquierda) tiene> 1 clave externa? –

+0

Estoy de acuerdo con @digEmAll: 'setkey (X2, y_id)' seguido de 'X2 [Y2, nomatch = 0]' es todo lo que necesita para su ejemplo. Y esto debería funcionar con varias claves también. Sin embargo, no estoy muy familiarizado con la sintaxis de la clave externa en SQL, así que si estás luchando con más claves, ¿podrías extender tu ejemplo? –

Respuesta

17

Buena pregunta. Tenga en cuenta la siguiente (la verdad enterrada) en ?data.table:

Cuando i es una data.table, x debe tener una clave. i se une a x usando la clave y las filas en x que coinciden. Se realiza una unión equitativa entre cada columna en i a cada columna en la clave x. La coincidencia es una búsqueda binaria en C compilada en el tiempo O (log n). Si i tiene menos columnas que la clave x, entonces muchas filas de x pueden coincidir con cada fila de i. Si i tiene más columnas que la clave x, las columnas de i no incluidas en la unión se incluyen en el resultado. Si i también tiene una clave, son las columnas de clave i las que se usan para coincidir con las columnas de clave x y se lleva a cabo una combinación binaria de las dos tablas.

Por lo tanto, la clave aquí es que i no tiene que estar codificado. Solo debe marcarse x.

X2 <- data.table(id = 11:15, y_id = c(14,14,11,12,12), key="id") 
    id y_id 
[1,] 11 14 
[2,] 12 14 
[3,] 13 11 
[4,] 14 12 
[5,] 15 12 
Y2 <- data.table(id = 11:15, b = letters[1:5], key="id") 
    id b 
[1,] 11 a 
[2,] 12 b 
[3,] 13 c 
[4,] 14 d 
[5,] 15 e 
Y2[J(X2$y_id)] # binary search for each item of (unsorted and unkeyed) i 
    id b 
[1,] 14 d 
[2,] 14 d 
[3,] 11 a 
[4,] 12 b 
[5,] 12 b 

o,

Y2[SJ(X2$y_id)] # binary merge of keyed i, see ?SJ 
    id b 
[1,] 11 a 
[2,] 12 b 
[3,] 12 b 
[4,] 14 d 
[5,] 14 d 

identical(Y2[J(X2$y_id)], Y2[X2$y_id]) 
[1] FALSE 
+0

gracias. pero 'idéntico (Y2 [J (X2 $ y_id)], Y2 [X2 $ y_id]) == TRUE', ¿hay alguna diferencia? –

+0

@David Han cambiado los datos de ejemplo para hacerlo más claro. Los datos de ejemplo anteriores tenían valores clave iguales a los números de fila, es decir, '1: 5'. –

Cuestiones relacionadas