Kapitel 3 Datamanipulering med dplyr
Det sägs ofta att en Data Scientist ägnar 80% av sin tid till att manipulera data så att den går att visualisera och modellera. Därför är det klokt att välja en metod och ett paket som underlättar det arbetet för dig.
I den här introduktionen kommer vi att fokusera på att använda paketet dplyr
för att göra datamanipuleringar. dplyr
är ett av de mest populära paketen i R och ger dig en bred verktygslåda för att manipulera data. dplyr
ingår också i ett samlingspaket tidyverse
och samlar flertalet paket för datamanipulering, visualisering och modellering.
dplyr
har ett antal verb för att göra manipuleringar:
filter()
där du väljer observationer baserat på deras värdenarrange()
som ändrar ordningen på raderselect()
för att välja variabler baserat på deras namnmutate()
för att skapa nya variabler baserat på funktionersummarise()
för att summera många värden till ett värde
Samtliga av dessa verb kan användas i kombination med funktionen group_by()
som innebär att du utför verben på flera grupper.
Alla verb i dplyr
är konsekventa. Det första argumentet är din data och i det andra argumentet specificerar du vad du vill göra med din data. Resultatet är alltid en ny data.frame.
3.1 Filter
Med filter kan du enkelt filtrera din data baserat på villkor.
Dessa villkor uttrycks med hjälp av relationsoperatorer
och logical operators
.
I R är dessa:
Relationsoperator | Symbol i R |
---|---|
och (and) | & |
eller(or) | | |
icke(not) | ! |
Logical Operators | Symbol i R |
---|---|
lika | == |
inte lika | != |
större än eller lika | >= |
mindre än eller lika | <= |
större än | > |
mindre än | < |
finns i | %in% |
Dessa kan du använda i filter()
.
PS: Det vanligaste misstaget i början av din R-karriär är att skriva =
istället för ==
.
Så här använder du operatorerna:
Hitta alla flyg som kom fram 08:30 under februari
## # A tibble: 9 x 19
## year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
## <int> <int> <int> <int> <int> <dbl> <int> <int>
## 1 2013 2 2 656 700 -4 830 839
## 2 2013 2 4 652 600 52 830 759
## 3 2013 2 6 629 630 -1 830 845
## 4 2013 2 13 633 636 -3 830 808
## 5 2013 2 18 717 700 17 830 832
## 6 2013 2 24 557 600 -3 830 837
## 7 2013 2 25 532 540 -8 830 850
## 8 2013 2 26 615 615 0 830 820
## 9 2013 2 28 621 630 -9 830 830
## # … with 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
## # tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
## # hour <dbl>, minute <dbl>, time_hour <dttm>
Hitta alla flygbolag som finns i c("UA", "DL")
i februari eller mars och som inte var försenade.
## # A tibble: 10,346 x 19
## year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
## <int> <int> <int> <int> <int> <dbl> <int> <int>
## 1 2013 2 1 520 525 -5 816 820
## 2 2013 2 1 527 530 -3 837 829
## 3 2013 2 1 554 601 -7 920 918
## 4 2013 2 1 558 600 -2 738 759
## 5 2013 2 1 559 600 -1 923 925
## 6 2013 2 1 600 600 0 833 837
## 7 2013 2 1 601 608 -7 703 725
## 8 2013 2 1 601 608 -7 723 755
## 9 2013 2 1 604 610 -6 752 817
## 10 2013 2 1 608 615 -7 837 842
## # … with 10,336 more rows, and 11 more variables: arr_delay <dbl>,
## # carrier <chr>, flight <int>, tailnum <chr>, origin <chr>, dest <chr>,
## # air_time <dbl>, distance <dbl>, hour <dbl>, minute <dbl>, time_hour <dttm>
3.1.1 Övning
Hur många plan…
- var försenade mer än 1 timme?
- skulle till Boston (“BOS”)
- lämnade JFK och var försenade
- lämnade JFK på julafton
- var försenade, men inte kom fram försent
- flög United Airlines (UA) eller American Airlines?
3.2 Arrange
arrange()
kastar om ordningen på dina rader enligt en av dig vald variabel. Exempelvis kanske vi vill sortera data på försenade avgångar dep_delay
.
## # A tibble: 336,776 x 19
## year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
## <int> <int> <int> <int> <int> <dbl> <int> <int>
## 1 2013 12 7 2040 2123 -43 40 2352
## 2 2013 2 3 2022 2055 -33 2240 2338
## 3 2013 11 10 1408 1440 -32 1549 1559
## 4 2013 1 11 1900 1930 -30 2233 2243
## 5 2013 1 29 1703 1730 -27 1947 1957
## 6 2013 8 9 729 755 -26 1002 955
## 7 2013 10 23 1907 1932 -25 2143 2143
## 8 2013 3 30 2030 2055 -25 2213 2250
## 9 2013 3 2 1431 1455 -24 1601 1631
## 10 2013 5 5 934 958 -24 1225 1309
## # … with 336,766 more rows, and 11 more variables: arr_delay <dbl>,
## # carrier <chr>, flight <int>, tailnum <chr>, origin <chr>, dest <chr>,
## # air_time <dbl>, distance <dbl>, hour <dbl>, minute <dbl>, time_hour <dttm>
arrange()
sorterar per default på sjunkande värde (ascending). Vill du sortera på stigande värde (descending) sätter du desc()
runt din variabel.
## # A tibble: 336,776 x 19
## year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
## <int> <int> <int> <int> <int> <dbl> <int> <int>
## 1 2013 1 9 641 900 1301 1242 1530
## 2 2013 6 15 1432 1935 1137 1607 2120
## 3 2013 1 10 1121 1635 1126 1239 1810
## 4 2013 9 20 1139 1845 1014 1457 2210
## 5 2013 7 22 845 1600 1005 1044 1815
## 6 2013 4 10 1100 1900 960 1342 2211
## 7 2013 3 17 2321 810 911 135 1020
## 8 2013 6 27 959 1900 899 1236 2226
## 9 2013 7 22 2257 759 898 121 1026
## 10 2013 12 5 756 1700 896 1058 2020
## # … with 336,766 more rows, and 11 more variables: arr_delay <dbl>,
## # carrier <chr>, flight <int>, tailnum <chr>, origin <chr>, dest <chr>,
## # air_time <dbl>, distance <dbl>, hour <dbl>, minute <dbl>, time_hour <dttm>
3.2.1 Övning
Hitta det flyg som…
- flög längst
- var mest försenat (när det kom fram)
3.3 Select
Medan arrange()
kastar om raderna så kastar select()
om kolumnerna. Men mest används den för att välja ut kolumner av intresse.
## # A tibble: 336,776 x 2
## dep_delay carrier
## <dbl> <chr>
## 1 2 UA
## 2 4 UA
## 3 2 AA
## 4 -1 B6
## 5 -6 DL
## 6 -4 UA
## 7 -5 B6
## 8 -3 EV
## 9 -3 B6
## 10 -2 AA
## # … with 336,766 more rows
Om du av något skäl vill flytta en kolumn till början kan du skriva:
## # A tibble: 336,776 x 19
## carrier year month day dep_time sched_dep_time dep_delay arr_time
## <chr> <int> <int> <int> <int> <int> <dbl> <int>
## 1 UA 2013 1 1 517 515 2 830
## 2 UA 2013 1 1 533 529 4 850
## 3 AA 2013 1 1 542 540 2 923
## 4 B6 2013 1 1 544 545 -1 1004
## 5 DL 2013 1 1 554 600 -6 812
## 6 UA 2013 1 1 554 558 -4 740
## 7 B6 2013 1 1 555 600 -5 913
## 8 EV 2013 1 1 557 600 -3 709
## 9 B6 2013 1 1 557 600 -3 838
## 10 AA 2013 1 1 558 600 -2 753
## # … with 336,766 more rows, and 11 more variables: sched_arr_time <int>,
## # arr_delay <dbl>, flight <int>, tailnum <chr>, origin <chr>, dest <chr>,
## # air_time <dbl>, distance <dbl>, hour <dbl>, minute <dbl>, time_hour <dttm>
Du kan även välja alla kolumner mellan två kolumner:
## # A tibble: 336,776 x 3
## year month day
## <int> <int> <int>
## 1 2013 1 1
## 2 2013 1 1
## 3 2013 1 1
## 4 2013 1 1
## 5 2013 1 1
## 6 2013 1 1
## 7 2013 1 1
## 8 2013 1 1
## 9 2013 1 1
## 10 2013 1 1
## # … with 336,766 more rows
Genom att sätta ett minus framför variabelnamnet exkluderar du variabeln.
## # A tibble: 336,776 x 18
## month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
## <int> <int> <int> <int> <dbl> <int> <int>
## 1 1 1 517 515 2 830 819
## 2 1 1 533 529 4 850 830
## 3 1 1 542 540 2 923 850
## 4 1 1 544 545 -1 1004 1022
## 5 1 1 554 600 -6 812 837
## 6 1 1 554 558 -4 740 728
## 7 1 1 555 600 -5 913 854
## 8 1 1 557 600 -3 709 723
## 9 1 1 557 600 -3 838 846
## 10 1 1 558 600 -2 753 745
## # … with 336,766 more rows, and 11 more variables: arr_delay <dbl>,
## # carrier <chr>, flight <int>, tailnum <chr>, origin <chr>, dest <chr>,
## # air_time <dbl>, distance <dbl>, hour <dbl>, minute <dbl>, time_hour <dttm>
3.3.0.1 select() plus hjälpfunktioner
select()
kommer med ett antal hjälpfunktioner:
starts_with("asd")
ends_with("air")
contains("flyg")
matches("asd")
num_range("flyg", 1:10)
De används för att identifiera kolumner baserat på text.
Exempelvis kan du hitta alla delay-kolumner med contains
.
## # A tibble: 336,776 x 2
## dep_delay arr_delay
## <dbl> <dbl>
## 1 2 11
## 2 4 20
## 3 2 33
## 4 -1 -18
## 5 -6 -25
## 6 -4 12
## 7 -5 19
## 8 -3 -14
## 9 -3 -8
## 10 -2 8
## # … with 336,766 more rows
3.3.0.2 rename()
En annan nyttig funktion är rename()
som kort och gott döper om variabler.
Formeln är rename(data, ny_variabel = gammal_variabel)
3.3.1 Övning
- Som innehåller “dep”
- Som börjar med “dep”
- Döp om
dep_delay
tillförsenad_avgång
3.4 Mutate
mutate()
används för att skapa nya variabler.
Exempelvis kan vi räkna ut hur mycket tid man vunnit om exempelvis flyget landar tidigare än avsett.
## # A tibble: 336,776 x 20
## year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
## <int> <int> <int> <int> <int> <dbl> <int> <int>
## 1 2013 1 1 517 515 2 830 819
## 2 2013 1 1 533 529 4 850 830
## 3 2013 1 1 542 540 2 923 850
## 4 2013 1 1 544 545 -1 1004 1022
## 5 2013 1 1 554 600 -6 812 837
## 6 2013 1 1 554 558 -4 740 728
## 7 2013 1 1 555 600 -5 913 854
## 8 2013 1 1 557 600 -3 709 723
## 9 2013 1 1 557 600 -3 838 846
## 10 2013 1 1 558 600 -2 753 745
## # … with 336,766 more rows, and 12 more variables: arr_delay <dbl>,
## # carrier <chr>, flight <int>, tailnum <chr>, origin <chr>, dest <chr>,
## # air_time <dbl>, distance <dbl>, hour <dbl>, minute <dbl>, time_hour <dttm>,
## # beer_time <dbl>
I mutate()
kan du även använda funktioner såsom mean()
.
## # A tibble: 336,776 x 20
## year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
## <int> <int> <int> <int> <int> <dbl> <int> <int>
## 1 2013 1 1 517 515 2 830 819
## 2 2013 1 1 533 529 4 850 830
## 3 2013 1 1 542 540 2 923 850
## 4 2013 1 1 544 545 -1 1004 1022
## 5 2013 1 1 554 600 -6 812 837
## 6 2013 1 1 554 558 -4 740 728
## 7 2013 1 1 555 600 -5 913 854
## 8 2013 1 1 557 600 -3 709 723
## 9 2013 1 1 557 600 -3 838 846
## 10 2013 1 1 558 600 -2 753 745
## # … with 336,766 more rows, and 12 more variables: arr_delay <dbl>,
## # carrier <chr>, flight <int>, tailnum <chr>, origin <chr>, dest <chr>,
## # air_time <dbl>, distance <dbl>, hour <dbl>, minute <dbl>, time_hour <dttm>,
## # mean_delay <dbl>
3.4.1 if_else()
En vanlig funktion i databearbetning är ifelse-satser.
I R gör du det enklast med funktionen if_else()
från dplyr
. Det finns även en inbyggd funktion som heter ifelse()
som mestadels fungerar bra men den från dplyr
är något mer stabil.
Du kan använda den i mutate:
## # A tibble: 336,776 x 20
## year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
## <int> <int> <int> <int> <int> <dbl> <int> <int>
## 1 2013 1 1 517 515 2 830 819
## 2 2013 1 1 533 529 4 850 830
## 3 2013 1 1 542 540 2 923 850
## 4 2013 1 1 544 545 -1 1004 1022
## 5 2013 1 1 554 600 -6 812 837
## 6 2013 1 1 554 558 -4 740 728
## 7 2013 1 1 555 600 -5 913 854
## 8 2013 1 1 557 600 -3 709 723
## 9 2013 1 1 557 600 -3 838 846
## 10 2013 1 1 558 600 -2 753 745
## # … with 336,766 more rows, and 12 more variables: arr_delay <dbl>,
## # carrier <chr>, flight <int>, tailnum <chr>, origin <chr>, dest <chr>,
## # air_time <dbl>, distance <dbl>, hour <dbl>, minute <dbl>, time_hour <dttm>,
## # försenad <chr>
Ibland vill man göra flera stycken if_else()
i samma, exempelvis om man vill dela upp en variabel i flera kategorier beroende på ett logiskt villkor. För att göra det kan du använda funktionen case_when()
.
mutate(flights, försenad_kat = case_when(
dep_delay < 0 ~ "före tid",
dep_delay == 0 ~ "i tid",
dep_delay > 0 ~ "försenad"))
## # A tibble: 336,776 x 20
## year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
## <int> <int> <int> <int> <int> <dbl> <int> <int>
## 1 2013 1 1 517 515 2 830 819
## 2 2013 1 1 533 529 4 850 830
## 3 2013 1 1 542 540 2 923 850
## 4 2013 1 1 544 545 -1 1004 1022
## 5 2013 1 1 554 600 -6 812 837
## 6 2013 1 1 554 558 -4 740 728
## 7 2013 1 1 555 600 -5 913 854
## 8 2013 1 1 557 600 -3 709 723
## 9 2013 1 1 557 600 -3 838 846
## 10 2013 1 1 558 600 -2 753 745
## # … with 336,766 more rows, and 12 more variables: arr_delay <dbl>,
## # carrier <chr>, flight <int>, tailnum <chr>, origin <chr>, dest <chr>,
## # air_time <dbl>, distance <dbl>, hour <dbl>, minute <dbl>, time_hour <dttm>,
## # försenad_kat <chr>
3.4.2 Andra funktioner
I mutate()
kan du använda de allra flesta funktionerna i R. Här är exempel på några funktioner som kan vara nyttiga i databearbetning:
- Funktioner för att ranka variabler:
rank()
,min_rank()
,dense_rank()
,percent_rank()
- För att logaritmiska funktioner:
log()
,log10()
- För kumulativa beräkningar:
cumsum()
,cummean()
- För att bara generera radnummer:
row_number()
- För att ta observation innan eller efter:
lead()
ochlag()
- För skapa variabler baserat på värde i andra variabler
if_else()
ochcase_when()
3.4.3 Övningar
- Skapa en variabel som innehåller den totala förseningen
- Rangordna flygens distans. Hur hanterar du fall där distansen är lika lång?
- Skapa en variabel som anger om flyget går på våren, hösten, vintern eller sommaren.
3.5 Summarise
Ofta vill man summera variabler för att få ut intressant information. Exempelvis vill vi här kanske veta en rad medelvärden.
## # A tibble: 1 x 1
## mean_dist
## <dbl>
## 1 1040.
## # A tibble: 1 x 1
## sum_dist
## <dbl>
## 1 350217607
## # A tibble: 1 x 1
## count
## <int>
## 1 336776
Men dessa värden är inte så intressanta i sig, utan vi vill kunna göra jämförelse. Då använder vi group_by()
.
group_by_flights <- group_by(flights, carrier)
summarise(group_by_flights,
mean_air_time = mean(air_time, na.rm = T),
mean_dep_delay = mean(dep_delay, na.rm = T),
mean_arr_delay = mean(arr_delay, na.rm = T))
## `summarise()` ungrouping output (override with `.groups` argument)
## # A tibble: 16 x 4
## carrier mean_air_time mean_dep_delay mean_arr_delay
## <chr> <dbl> <dbl> <dbl>
## 1 9E 86.8 16.7 7.38
## 2 AA 189. 8.59 0.364
## 3 AS 326. 5.80 -9.93
## 4 B6 151. 13.0 9.46
## 5 DL 174. 9.26 1.64
## 6 EV 90.1 20.0 15.8
## 7 F9 230. 20.2 21.9
## 8 FL 101. 18.7 20.1
## 9 HA 623. 4.90 -6.92
## 10 MQ 91.2 10.6 10.8
## 11 OO 83.5 12.6 11.9
## 12 UA 212. 12.1 3.56
## 13 US 88.6 3.78 2.13
## 14 VX 337. 12.9 1.76
## 15 WN 148. 17.7 9.65
## 16 YV 65.7 19.0 15.6
I summarise()
kan du använda en rad olika funktioner såsom sum()
för summeringar, median()
etc.
3.5.0.1 Övningar
- Vilken flygplats har högst medelvärde förförseningar från flygplatsen?
- Vilken flygplats tar emot minst flyg?
3.5.0.2 Väv ihop verben med %>%
Med %>%
(som kallas för pipe
and kan uttalas som and then
) kan länka ihop flera uttryck i R. Det gör framför allt din kod mer lättläst.
Med %>%
kan du exempelvis först filtrera, sen gruppera och till sist summera, allt i samma uttryck.
flights %>%
filter(dep_delay < 60) %>%
group_by(carrier) %>%
summarise(mean_dep_delay = mean(dep_delay, na.rm = T))
## `summarise()` ungrouping output (override with `.groups` argument)
## # A tibble: 16 x 2
## carrier mean_dep_delay
## <chr> <dbl>
## 1 9E 2.96
## 2 AA 0.890
## 3 AS -0.719
## 4 B6 3.26
## 5 DL 1.76
## 6 EV 4.65
## 7 F9 5.09
## 8 FL 4.72
## 9 HA -2.47
## 10 MQ 1.48
## 11 OO -2.88
## 12 UA 4.33
## 13 US -0.744
## 14 VX 2.70
## 15 WN 6.60
## 16 YV 2.25
Du läser alltså:
Första tar vi flights
and then
filtrerar vi på dep_delay
and then
grupperar vi på carrier
and then
räknar vi ut medelvärde på dep_delay
.
Vilket är mycket mer lättläst än motsvarigheten med parenteser:
3.5.0.3 count()
Du kan i summarise()
räkna antalet observationer med funktionen n()
.
## `summarise()` ungrouping output (override with `.groups` argument)
## # A tibble: 16 x 2
## carrier count
## <chr> <int>
## 1 9E 18460
## 2 AA 32729
## 3 AS 714
## 4 B6 54635
## 5 DL 48110
## 6 EV 54173
## 7 F9 685
## 8 FL 3260
## 9 HA 342
## 10 MQ 26397
## 11 OO 32
## 12 UA 58665
## 13 US 20536
## 14 VX 5162
## 15 WN 12275
## 16 YV 601
Men istället för att göra det här kan du använda funktionen count()
## # A tibble: 16 x 2
## # Groups: carrier [16]
## carrier n
## <chr> <int>
## 1 9E 18460
## 2 AA 32729
## 3 AS 714
## 4 B6 54635
## 5 DL 48110
## 6 EV 54173
## 7 F9 685
## 8 FL 3260
## 9 HA 342
## 10 MQ 26397
## 11 OO 32
## 12 UA 58665
## 13 US 20536
## 14 VX 5162
## 15 WN 12275
## 16 YV 601
3.6 sample_n()
Att göra slumpmässiga urval är en vanlig arbetsuppgift för en data scientist. Det gör du enkelt med sample_n()
från dplyr
.
Om du vill ta ett slumpmässigt urval om 10 från exempelvis flights
gör du bara:
## # A tibble: 10 x 19
## year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
## <int> <int> <int> <int> <int> <dbl> <int> <int>
## 1 2013 4 15 1403 1348 15 1631 1636
## 2 2013 11 6 1046 1049 -3 1233 1239
## 3 2013 11 26 1254 1300 -6 1430 1428
## 4 2013 11 1 1026 1030 -4 1249 1252
## 5 2013 12 11 2152 2159 -7 1 2359
## 6 2013 10 10 857 900 -3 1145 1144
## 7 2013 7 17 921 915 6 1154 1215
## 8 2013 7 27 629 630 -1 832 835
## 9 2013 9 6 1734 1735 -1 1935 1944
## 10 2013 6 15 1301 1309 -8 1411 1424
## # … with 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
## # tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
## # hour <dbl>, minute <dbl>, time_hour <dttm>
Om du istället vill ta ett urval som baseras på procent kan du använda sample_frac
, här för 0.01%
## # A tibble: 337 x 19
## year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
## <int> <int> <int> <int> <int> <dbl> <int> <int>
## 1 2013 6 17 1140 1145 -5 1311 1320
## 2 2013 12 31 1310 1215 55 1545 1445
## 3 2013 12 8 1515 1525 -10 1738 1720
## 4 2013 12 8 1905 1807 58 2314 1950
## 5 2013 12 3 1453 1454 -1 1937 1951
## 6 2013 9 17 809 815 -6 1052 1121
## 7 2013 9 30 806 815 -9 1019 1040
## 8 2013 8 7 917 849 28 1139 1115
## 9 2013 10 25 558 600 -2 904 858
## 10 2013 10 27 1056 1100 -4 1247 1300
## # … with 327 more rows, and 11 more variables: arr_delay <dbl>, carrier <chr>,
## # flight <int>, tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>,
## # distance <dbl>, hour <dbl>, minute <dbl>, time_hour <dttm>
3.6.1 Övning
- Vilken månad ska du flyga under för att undvika förseningar?
- Vilken tid ska du flyga för att undvika förseningar?
- Hitta det flygbolag som flyger till flest destinationer, rangordna flygbolagen baserat på den informationen.