Programmering

R data.tabelsymboler og operatører du bør kjenne

R data.table-kode blir mer effektiv - og elegant - når du utnytter de spesielle symbolene og funksjonene. Med dette i bakhodet vil vi se på noen spesielle måter å delmengde, telle og opprette nye kolonner på.

For denne demoen skal jeg bruke data fra 2019 Stack Overflow-utviklerundersøkelsen, med omtrent 90 000 svar. Hvis du vil følge med, kan du laste ned dataene fra Stack Overflow.

Hvis data.table-pakken ikke er installert på systemet ditt, installerer du det fra CRAN og laster det som vanlig med bibliotek (data.table). For å starte, kan det være lurt å lese i bare de første radene av datasettet for å gjøre det lettere å undersøke datastrukturen. Du kan gjøre det med data.table’s fread () funksjon og nrows argument. Jeg leser i ti rader:

data_sample <- fread ("data / survey_results_public.csv", nrows = 10)

Som du ser, er det 85 kolonner å undersøke. (Hvis du vil vite hva alle kolonnene betyr, er det filer i nedlastingen med dataskjemaet og en PDF av den opprinnelige undersøkelsen.)

For å lese inn alle dataene bruker jeg:

mydt <- fread ("data / survey_results_public.csv")

Deretter oppretter jeg en ny data.tabel med bare noen få kolonner for å gjøre det lettere å jobbe med og se resultater. En påminnelse om at data.table bruker denne grunnleggende syntaksen:

mydt [i, j, av]

Innledningen til data.table-pakken sier å lese dette som "ta dt, delmengde eller ordne rader med i, beregne j, gruppert etter." Husk at i og j ligner på basen R: s rekkefølge: rad først, kolonnene andre. Så jeg er for operasjoner du vil gjøre på rader (velge rader basert på radnummer eller forhold); j er hva du vil gjøre med kolonner (velg kolonner eller opprett nye kolonner fra beregninger). Vær imidlertid også oppmerksom på at du kan gjøre mye mer innenfor data.table-parenteser enn en base R-dataramme. Og delen "etter" er ny for data.table.

Siden jeg er velge kolonner, går denne koden i "j" -punktet, noe som betyr at parentesene trenger et komma først for å la "i" -punktet være tomt:

mydt [, j]

Velg datatabellkolonner

En av tingene jeg liker med data.table er at det er enkelt å velge kolonner enten sitert eller ikke sitert. Ikke sitert er ofte mer praktisk (det er vanligvis den tidyverse måten). Men sitert er nyttig hvis du bruker data.table i dine egne funksjoner, eller hvis du vil passere i en vektor du opprettet et annet sted i koden din.

Du kan velge datatabellkolonner på den typiske basis R-måten, med en konvensjonell vektor av siterte kolonnenavn. For eksempel:

dt1 <- mydt [, c ("LanguageWorkedWith", "LanguageDesireNextYear",

"OpenSourcer", "CurrencySymbol", "ConvertedComp",

“Hobbyist”)]

Hvis du vil bruke dem unsitert, opprett en liste i stedet for en vektor og du kan gi de ikke siterte navnene.

dt1 <- mydt [, list (LanguageWorkedWith, LanguageDesireNextYear,

OpenSourcer, CurrencySymbol, ConvertedComp,

Hobbyist)]

Og nå kommer vi til vårt første spesielle symbol. I stedet for å skrive ut liste(), kan du bare bruke en prikk:

dt1 <- mydt [,. (LanguageWorkedWith, LanguageDesireNextYear,

OpenSourcer, CurrencySymbol, ConvertedComp,

Hobbyist)]

At .() er en snarvei for liste() innsiden av data. tabellparenteser.

Hva om du vil bruke en allerede eksisterende vektor med kolonnenavn? Å sette vektorobjektnavnet i data.table-parenteser fungerer ikke. Hvis jeg lager en vektor med siterte kolonnenavn, slik:

mycols <- c ("LanguageWorkedWith", "LanguageDesireNextYear",

"OpenSourcer", "CurrencySymbol", "ConvertedComp", "Hobbyist")

Da vil denne kodenikke arbeid:

dt1 <- mydt [, mycols]

I stedet må du sette .. (det er to prikker) foran vektorobjektnavnet:

dt1 <- mydt [, ..mycols]

Hvorfor to prikker? Det virket litt tilfeldig for meg til jeg leste forklaringen. Tenk på det som de to punktene i en Unix kommandolinjeterminal som beveger deg opp en katalog. Her rykker du opp en navneområdet, fra miljøet i data.table parenteser opp til det globale miljøet. (Det hjelper meg virkelig å huske det!)

Tell data.table-rader

Videre til neste symbol. For å telle etter gruppe kan du bruke data.table’s .N symbol, hvor.N står for "antall rader." Det kan være totalt antall rader, eller antall rader per gruppe hvis du samler i "etter" -delen.

Dette uttrykket returnerer det totale antall rader i data.table:

mydt [, .N]

Følgende eksempel beregner antall rader gruppert av en variabel: om folk i undersøkelsen også koder som en hobby ( Hobbyist variabel).

mydt [, .N, hobbyist]

# returnerer:

Hobbyist N 1: Ja 71257 2: Nei 17626

Du kan bruke det vanlige kolonnenavnet innenfor data.table-parenteser hvis det bare er en variabel. Hvis du vil gruppere etter to eller flere variabler, bruker du . symbol. For eksempel:

mydt [, .N,. (Hobbyist, OpenSourcer)]

For å bestille resultater fra høyeste til laveste, kan du legge til et andre sett med parenteser etter den første. De .N symbol genererer automatisk en kolonne som heter N (selvfølgelig kan du gi den nytt navn hvis du vil), slik at rekkefølge etter antall rader kan se omtrent slik ut:

mydt [, .N,. (Hobbyist, OpenSourcer)] [ordre (Hobbyist, -N)]

Når jeg lærer data.table-kode, synes jeg det er nyttig å lese den trinnvis. Så jeg ville lest dette som "For alle rader i mydt (siden det ikke er noe i "I" -punktet), teller antall rader, gruppert etter Hobbyist og OpenSourcer. Bestill så først av Hobbyist og deretter antall rader som synker. ”

Det tilsvarer denne dplyr-koden:

mydf%>%

count (Hobbyist, OpenSourcer)%>%

ordre (hobbyist, -n)

Hvis du finner den tidyverse konvensjonelle flerlinjemetoden mer lesbar, fungerer denne datatabellkoden også:

mydt [, .N,

. (Hobbyist, OpenSourcer)] [

ordre (hobbyist, -N)

]

Legg til kolonner i en datatabell

Deretter vil jeg legge til kolonner for å se om hver respondent bruker R, om de bruker Python, om de bruker begge deler, eller om de ikke bruker noen av dem. De SpråkArbeidetMed kolonnen har informasjon om språkene som brukes, og noen rader med dataene ser slik ut:

Sharon Machlis

Hvert svar er en enkelt tegnstreng. De fleste har flere språk atskilt med semikolon.

Som ofte er det lettere å søke etter Python enn R, siden du ikke bare kan søke etter "R" i strengen (Ruby og Rust inneholder også en stor R) slik du kan søke etter "Python". Dette er den enklere koden for å lage en SANN / FALSK vektor som sjekker om hver streng i SpråkArbeidetMed inneholder Python:

ifelse (LanguageWorkedWith% like% "Python", TRUE, FALSE)

Hvis du kjenner SQL, vil du gjenkjenne den "som" syntaksen. Jeg, vel, liker %som%. Det er en fin strømlinjeformet måte å sjekke for mønstermatching. Funksjonsdokumentasjonen sier at den er ment å brukes i data.table-parenteser, men faktisk kan du bruke den i hvilken som helst av koden din, ikke bare med data.tables. Jeg sjekket med data.table-skaperen Matt Dowle, som sa at rådet om å bruke det i parentesene er fordi noe ekstra ytelsesoptimalisering skjer der.

Deretter er her kode for å legge til en kolonne kalt PythonUser til data.table:

dt1 [, PythonUser: = ifelse (LanguageWorkedWith% like% "Python", TRUE, FALSE)]

Legg merke til := operatør. Python har også en operatør, og helt siden jeg hørte det kalte "hvalrossoperatøren", så kaller jeg det. Jeg tror det er offisielt "oppdrag med referanse." Det er fordi koden ovenfor endret det eksisterende objektet dt1 data.table ved å legge til den nye kolonnen - uten trenger å lagre den i en ny variabel.

For å søke etter R, bruker jeg det vanlige uttrykket "\ bR \ b" som sier: “Finn et mønster som begynner med en ordgrense - \ b, så en R, og avslutt deretter med en annen ordgrense. (Jeg kan ikke bare se etter "R;" fordi det siste elementet i hver streng ikke har semikolon.)

Dette legger til en RUser-kolonne til dt1:

dt1 [, RUser: = ifelse (LanguageWorkedWith% like% "\ bR \ b", TRUE, FALSE)]

Hvis du vil legge til begge kolonnene samtidig med := du må gjøre den hvalrossoperatøren til en funksjon ved å tilbakestille den, slik:

dt1 [, `:=`(

PythonUser = ifelse (LanguageWorkedWith% like% "Python", TRUE, FALSE),

RUser = ifelse (LanguageWorkedWith% like% "\ bR \ b", TRUE, FALSE)

)]

Mer nyttige data.table-operatører

Det er flere andre datatabelloperatører som er verdt å vite. De%mellom% operatøren har denne syntaksen:

myvector% mellom% c (nedre verdi, øvre verdi)

Så hvis jeg vil filtrere etter alle svar der kompensasjonen var mellom 50 000 og 100 000 betalt i amerikanske dollar, fungerer denne koden:

comp_50_100k <- dt1 [CurrencySymbol == "USD" &

ConvertedComp% mellom% c (50000, 100000)]

Den andre linjen over er tilstanden mellom. Merk at %mellom% operatøren inkluderer både nedre og øvre verdier når den sjekker.

En annen nyttig operatør er %hake%. Det fungerer som base R’er %i% men er optimalisert for hastighet og er for kun tegnvektorer. Så hvis jeg vil filtrere etter alle radene der OpenSourcer-kolonnen enten var "Aldri" eller "Mindre enn en gang per år", fungerer denne koden:

rareos <- dt1 [OpenSourcer% chin% c ("Aldri", "Mindre enn en gang per år")]

Dette ligner ganske mye på base R, bortsett fra at base R må spesifisere datarammenavnet inne i braketten og også krever et komma etter filteruttrykket:

rareos_df <- df1 [df1 $ OpenSourcer% i% c ("Aldri", "Mindre enn en gang per år"),]

Den nye funksjonen fcase ()

For denne siste demo vil jeg begynne med å lage en ny data.tabell med bare personer som rapporterte kompensasjon i amerikanske dollar:

usd <- dt1 [CurrencySymbol == "USD" &! is.na (ConvertedComp)]

Deretter oppretter jeg en ny kolonne som heter Språk for om noen bruker bare R, bare Python, begge deler eller ingen av dem. Og jeg skal bruke det nye fcase () funksjon. Da artikkelen ble publisert, fcase () var bare tilgjengelig i data.tables utviklingsversjon. Hvis du allerede har data.table installert, kan du oppdatere til den siste dev-versjonen med denne kommandoen:

data.table :: update.dev.pkg ()

Funksjonen fcase () ligner på SQL SAK NÅR uttalelse og dplyr’s case_when () funksjon. Den grunnleggende syntaksen erfcase (condition1, "value1", condition2, "value2") og så videre. En standardverdi for "alt annet" kan legges til med standard = verdi.

Her er kode for å opprette den nye språkkolonnen:

usd [, Språk: = fcase (

RUser &! PythonUser, "R",

PythonUser &! RUser, "Python",

PythonUser & RUser, "Begge",

! PythonUser &! RUser, "Ingen av dem"

)]

Jeg setter hver tilstand på en egen linje fordi jeg synes det er lettere å lese, men du trenger ikke.

En advarsel: Hvis du bruker RStudio, oppdateres ikke data.table-strukturen automatisk øverst til høyre i RStudio-ruten etter at du har opprettet en ny kolonne med hvalrossoperatøren. Du må klikke på oppdateringsikonet manuelt for å se endringer i antall kolonner.

Det er noen få andre symboler jeg ikke vil dekke i denne artikkelen. Du kan finne en liste over dem i "spesielle symboler" data.table hjelpefilen ved å kjøre hjelp ("spesielle symboler"). En av de mest nyttige, .SD, har allerede sin egen Do More With R-artikkel og video, "Hvordan bruke .SD i R data.table-pakken."

For flere R-tips, gå til "Gjør mer med R" -siden på eller sjekk ut "Gjør mer med R"-YouTube-spillelisten.

$config[zx-auto] not found$config[zx-overlay] not found