¿Qué sintaxis data.table para unirse a izquierda (una columna) a preferir

Pregunta hecha: hace 8 meses Ultima actividad: hace 4 meses
up 7 down

¿Cómo debería empezar a pensar en lo que yo prefiero sintaxis?

Mi criterio es la eficiencia (este es el número uno), y también la legibilidad/mantenibilidad.

Esta

A <- B[A, on = .(id)] # wow such. concision

O eso

A[B, on = .(id), comment := i.comment]

O incluso (como sugiere PoGibas):

A <- merge(A, B, all.x = TRUE)

Para completar a continuación una forma más básica es utilizar match():

A[, comment := B[chmatch(A[["id"]], id), comment]]

Datos de ejemplo:

library(data.table)
A <- data.table(id = letters[1:10], amount = rnorm(10)^2)
B <- data.table(id = c("c", "d", "e"), comment = c("big", "slow", "nice"))

1 respuesta

up 15 down accepted

Yo prefiero la "actualización de unirse" modismo para la eficiencia y facilidad de mantenimiento: **

DT[WHERE, v := FROM[.SD, on=, x.v]]

Es una extensión de lo que se muestra en vignette("datatable-reference-semantics") en "actualizar algunas filas de columnas por referencia - sub-asignar por referencia". Una vez que hay una viñeta disponible en combinaciones, que también debe ser una buena referencia.

Esta es eficiente puesto que utiliza solamente las filas seleccionadas por WHERE y modifica o agrega la columna en el lugar, en vez de hacer una nueva tabla como la izquierda más concisa unirse FROM[DT, on=].

Hace que mi código sea más legible ya que puedo ver fácilmente que el punto de la unión es añadir la columna v; y yo no tengo que pensar en la jerga "izquierda"/"derecho" de SQL o si el número de filas se conserva después de la unión.

Es útil para el mantenimiento del código ya que si más adelante quiero averiguar cómo DT consiguió una columna llamada v, Puedo buscar mi código de v :=, mientras FROM[DT, on=] oscurece que se están añadiendo nuevas columnas. Además, permite la WHERE condición, mientras que la izquierda se unen no lo hace. Esto puede ser útil, por ejemplo, si utilizando FROM para "llenar" AN en una columna existente v.


En comparación con la otra actualización de unirse enfoque DT[FROM, on=, v := i.v], Puedo pensar en dos ventajas. En primer lugar está la opción de usar el WHERE cláusula, y la segunda es a través de la transparencia advertencias cuando hay problemas con la unión, como duplicados en partidos FROM condicionada a la on= reglas. Aquí está una ilustración que se extiende el ejemplo de la OP:

library(data.table)
A <- data.table(id = letters[1:10], amount = rnorm(10)^2)
B2 <- data.table(
  id = c("c", "d", "e", "e"), 
  ord = 1:4, 
  comment = c("big", "slow", "nice", "nooice")
)

# left-joiny update
A[B2, on=.(id), comment := i.comment, verbose=TRUE]
# Calculated ad hoc index in 0.000s elapsed (0.000s cpu) 
# Starting bmerge ...done in 0.000s elapsed (0.000s cpu) 
# Detected that j uses these columns: comment,i.comment 
# Assigning to 4 row subset of 10 rows

# my preferred update
A[, comment2 := B2[A, on=.(id), x.comment]]
# Warning message:
# In `[.data.table`(A, , `:=`(comment2, B2[A, on = .(id), x.comment])) :
#   Supplied 11 items to be assigned to 10 items of column 'comment2' (1 unused)

    id     amount comment comment2
 1:  a 0.20000990    <NA>     <NA>
 2:  b 1.42146573    <NA>     <NA>
 3:  c 0.73047544     big      big
 4:  d 0.04128676    slow     slow
 5:  e 0.82195377  nooice     nice
 6:  f 0.39013550    <NA>   nooice
 7:  g 0.27019768    <NA>     <NA>
 8:  h 0.36017876    <NA>     <NA>
 9:  i 1.81865721    <NA>     <NA>
10:  j 4.86711754    <NA>     <NA>

En la actualización de izquierda a unirse con sabor, que en silencio obtener el valor final de comment a pesar de que hay dos partidos para id == "e"; mientras que en la otra actualización, se obtiene un mensaje de advertencia útil (actualizado a un error en una versión futura). Incluso encender verbose=TRUE con el enfoque izquierda articulación no es informativo - que dice que hay cuatro filas de ser actualizados, pero no dice que una fila se actualiza dos veces.


Me parece que este enfoque funciona mejor cuando mi datos se organizan en un conjunto de tablas ordenadas/relacionales. Una buena referencia en el que se El artículo de Hadley Wickham.

** En este idioma, el on= parte deben completarse con los nombres y las reglas columna de combinación, como on=.(id) o on=.(from_date >= dt_date). disposiciones adicionales de unirse se pueden pasar con roll=, mult= y nomatch=. Ver ?data.table para detalles. Gracias a @RYoda para que tome nota de este punto en los comentarios.

Aquí es un ejemplo más complicado de Matt Dowle explicar roll=: Encontrar tiempo para la aparición cercana de particular valor para cada fila

Otro ejemplo relacionado con: Izquierda se unen mediante data.table