Zoeken…


Invoering

Een join combineert twee tabellen met gerelateerde kolommen. De term omvat een breed scala aan bewerkingen, in wezen alles behalve het toevoegen van de twee tabellen . "Samenvoegen" is een synoniem. Typ ?`[.data.table` voor de officiële documenten.

Syntaxis

  • x [i, aan, j]
    # join: data.table x & data.table of lijst i
  • x [! i, on, j]
    # anti-join

Opmerkingen

Werken met sleuteltabellen

Als x & i een sleutel hebben of x is ingetoetst om overeen te komen met de eerste paar kolommen van i , dan kan de on worden overgeslagen zoals x[i] .

Duidelijke gemeenschappelijke kolomnamen

In j van x[i, on, j] kunnen kolommen van i worden aangeduid met i.* -Voorvoegsels.

Groeperen op subsets

In j van x[i, on, j, by=.EACHI] , wordt j berekend voor elke rij van i .

Dit is de enige waarde van de by waard om te gebruiken. Voor elke andere waarde zijn kolommen van i niet beschikbaar.

Werk waarden bij in een join

Wanneer gegevens "netjes" zijn , zijn ze vaak georganiseerd in verschillende tabellen. Om de gegevens voor analyse te combineren, moeten we de ene tabel "bijwerken" met waarden uit een andere.

We hebben bijvoorbeeld verkoopgegevens voor uitvoeringen, waarbij kenmerken van de uitvoerder (hun budget) en van de locatie (de populatie) worden opgeslagen in afzonderlijke tabellen:

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

Wanneer we klaar zijn om wat analyses te doen, moeten we variabelen uit deze andere tabellen pakken:

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

Er wordt een copy gemaakt om te voorkomen dat de onbewerkte gegevens worden besmet, maar we kunnen in plaats daarvan rechtstreeks aan mainDT .

Voordelen van het gebruik van afzonderlijke tabellen

De voordelen van deze structuur worden behandeld in het artikel over opgeruimde gegevens, maar in deze context:

  1. Ontbrekende gegevens traceren. Alleen rijen die overeenkomen in de samenvoeging ontvangen een opdracht. We hebben geen gegevens voor geo_id == "MO" hierboven, dus de variabelen zijn NA in onze laatste tabel. Als we dit soort ontbrekende gegevens onverwacht zien, kunnen we het herleiden tot de ontbrekende waarneming in de geoDT tabel en onderzoeken we of we een gegevensprobleem hebben dat kan worden verholpen.

  2. Begrijpelijkheid. Bij het bouwen van ons statistisch model kan het belangrijk zijn om in gedachten te houden dat het budget constant is voor elke uitvoerder. Over het algemeen levert het begrijpen van de structuur van de gegevens winst op.

  3. Geheugen grootte. Er kan een groot aantal uitvoerder- en locatiekenmerken zijn die niet in het statistische model terechtkomen. Op deze manier hoeven we ze niet op te nemen in de (mogelijk massieve) tabel die wordt gebruikt voor analyse.

Programmatisch bepalende kolommen

Als er veel kolommen in pDT , maar we er slechts een paar willen selecteren, kunnen we gebruiken

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

De haakjes rondom (p_cols) := zijn essentieel, zoals vermeld in het document over het maken van kolommen .

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

Intuïtie

Zie x[i] als het selecteren van een subset van x voor elke rij van i . Deze syntaxis weerspiegelt matrixsubsetting in basis R en is consistent met het eerste argument dat "waar" betekent, in DT[where, select|update|do, by] .

Je kunt je afvragen waarom deze nieuwe syntaxis het leren waard is, omdat merge(x,i) nog steeds werkt met data.tables. Het korte antwoord is dat we het meestal willen samenvoegen en dan iets verder willen doen. De syntaxis x[i] legt dit gebruikspatroon bondig vast en maakt ook een efficiëntere berekening mogelijk. Lees FAQs 1.12 en 2.14 voor een meer gedetailleerde uitleg.

Meerdere overeenkomende rijen verwerken

Standaard wordt elke rij van a bijpassende rij van b geretourneerd:

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

Dit kan worden aangepast met mult :

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

Ongeëvenaarde rijen verwerken

Standaard worden niet-overeenkomende rijen van a nog steeds weergegeven in het resultaat:

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

Gebruik nomatch om deze te verbergen:

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

Merk op dat x[i] zal proberen NA's in i te matchen.

Wedstrijden tellen terug

Gebruik .N en by=.EACHI om het aantal overeenkomsten voor elke rij van i 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
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow