Ricerca…


introduzione

Un join combina due tabelle contenenti colonne correlate. Il termine copre una vasta gamma di operazioni, essenzialmente tutto tranne l' aggiunta delle due tabelle . "Unisci" è un sinonimo. Digitare ?`[.data.table` per i documenti ufficiali.

Sintassi

  • x [i, on, j]
    # join: data.table x & data.table o lista i
  • x [! i, on, j]
    # anti-join

Osservazioni

Lavorare con tabelle con chiave

Se x & i hanno una chiave o x è calettati per abbinare i 's prime colonne, allora la on possono essere ignorati come x[i] .

Nomi di colonne disambiguanti in comune

In j di x[i, on, j] , le colonne di i possono essere riferite con prefissi i.* .

Raggruppamento su sottoinsiemi

In j di x[i, on, j, by=.EACHI] , j viene calcolato per ogni riga di i .

Questo è l'unico valore by vale la pena utilizzare. Per qualsiasi altro valore, le colonne di i non sono disponibili.

Aggiorna valori in un join

Quando i dati sono "ordinati" , è spesso organizzato in più tabelle. Per combinare i dati per l'analisi, dobbiamo "aggiornare" una tabella con i valori di un'altra.

Ad esempio, potremmo avere dati di vendita per le prestazioni, in cui gli attributi dell'esecutore (il loro budget) e della posizione (la sua popolazione) sono memorizzati in tabelle separate:

set.seed(1)
mainDT = data.table(
  p_id = rep(LETTERS[1:2], c(2,4)), 
  geo_id = sample(rep(state.abb[c(1,25,50)], 3:1)), 
  sales = sample(100, 6)
)
pDT   = data.table(id = LETTERS[1:2], budget = c(60, 75))
geoDT = data.table(id = state.abb[c(1,50)], pop = c(100, 200))

mainDT # sales data
#    p_id geo_id sales
# 1:    A     AL    95
# 2:    A     WY    66
# 3:    B     AL    62
# 4:    B     MO     6
# 5:    B     AL    20
# 6:    B     MO    17


pDT # performer attributes
#    id budget
# 1:  A     60
# 2:  B     75

geoDT # location attributes
#    id pop
# 1: AL 100
# 2: WY 200

Quando siamo pronti per fare qualche analisi, dobbiamo prendere le variabili da queste altre tabelle:

DT = copy(mainDT)

DT[pDT, on=.(p_id = id), budget := i.budget]
DT[geoDT, on=.(geo_id = id), pop := i.pop]

#    p_id geo_id sales budget pop
# 1:    A     AL    95     60 100
# 2:    A     WY    66     60 200
# 3:    B     AL    62     75 100
# 4:    B     MO     6     75  NA
# 5:    B     AL    20     75 100
# 6:    B     MO    17     75  NA

Viene mainDT una copy per evitare di contaminare i dati grezzi, ma potremmo invece lavorare direttamente su mainDT .

Vantaggi nell'utilizzo di tabelle separate

I vantaggi di questa struttura sono trattati nel documento sui dati ordinati, ma in questo contesto:

  1. Tracciamento dei dati mancanti. Solo le righe che corrispondono nell'unione ricevono un compito. Non abbiamo dati per geo_id == "MO" sopra, quindi le sue variabili sono NA nella nostra tabella finale. Se vediamo inaspettatamente dati mancanti di questo tipo, possiamo risalire all'osservazione mancante nella tabella geoDT e indagare da lì se abbiamo un problema di dati che può essere risolto.

  2. Comprensibilità. Nel costruire il nostro modello statistico, potrebbe essere importante tenere a mente che il budget è costante per ogni attore. In generale, capire la struttura dei dati paga i dividendi.

  3. Dimensione della memoria. Potrebbe esserci un gran numero di attributi esecutore e posizione che non finiscono nel modello statistico. In questo modo, non è necessario includerli nella (possibilmente massiccia) tabella utilizzata per l'analisi.

Determinazione a livello di codice delle colonne

Se ci sono molte colonne in pDT , ma vogliamo solo selezionarne alcune, possiamo usarle

p_cols = "budget"
DT[pDT, on=.(p_id = id), (p_cols) := mget(sprintf("i.%s", p_cols))]

Le parentesi intorno (p_cols) := sono essenziali, come indicato nel documento sulla creazione di colonne .

Equi-join

# example data
a = data.table(id = c(1L, 1L, 2L, 3L, NA_integer_), x = 11:15)
#    id  x
# 1:  1 11
# 2:  1 12
# 3:  2 13
# 4:  3 14
# 5: NA 15

b = data.table(id = 1:2, y = -(1:2))
#    id  y
# 1:  1 -1
# 2:  2 -2

Intuizione

Pensa a x[i] come selezionando un sottoinsieme di x per ogni riga di i . Questa sintassi rispecchia il subset matrice in base R ed è coerente con il primo argomento che significa "dove", in DT[where, select|update|do, by] .

Ci si potrebbe chiedere perché valga la pena imparare questa nuova sintassi, dato che merge(x,i) funziona ancora con data.tables. La risposta breve è che di solito vogliamo unire e quindi fare qualcosa di più. La sintassi x[i] cattura concisamente questo schema di utilizzo e consente anche un calcolo più efficiente. Per una spiegazione più dettagliata, leggere le domande frequenti 1.12 e 2.14 .

Gestione di righe con corrispondenza multipla

Per impostazione predefinita, viene restituita ogni riga di a corrispondenza di ogni riga di b :

a[b, on="id"]
#    id  x  y
# 1:  1 11 -1
# 2:  1 12 -1
# 3:  2 13 -2

Questo può essere ottimizzato con mult :

a[b, on="id", mult="first"]
#    id  x  y
# 1:  1 11 -1
# 2:  2 13 -2

Gestione di righe non corrispondenti

Per impostazione predefinita, le righe senza precedenti di a ancora la loro comparsa nel risultato:

b[a, on="id"]
#    id  y  x
# 1:  1 -1 11
# 2:  1 -1 12
# 3:  2 -2 13
# 4:  3 NA 14
# 5: NA NA 15

Per nasconderli, usa nomatch :

b[a, on="id", nomatch=0]
#    id  y  x
# 1:  1 -1 11
# 2:  1 -1 12
# 3:  2 -2 13

Si noti che x[i] tenterà di far corrispondere le NA in i .

Le partite di conteggio sono tornate

Per contare il numero di corrispondenze per ogni riga di i , utilizzare .N e by=.EACHI .

b[a, on="id", .N, by=.EACHI]
#    id N
# 1:  1 1
# 2:  1 1
# 3:  2 1
# 4:  3 0
# 5: NA 0


Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow