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
library(dplyr)
library(nycflights13)
filter(flights, month == 2, arr_time == 830)
## # 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.
filter(flights, carrier %in% c("UA", "DL"), month == 2 | month == 3, dep_delay <= 0)
## # 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
Öppna dokumentet
databearbetning-övningar.Rmd
Börja med att ladda
tidyverse
ochnycflights13
Spara
flights
som en data.frame i dinenvironment
, genomflights <- flights
PS. flights
är en tibble
som bara är en lite snyggare variant av en data.frame
.
Nu till övningarna:
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
.
arrange(flights, 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.
arrange(flights, desc(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 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.
select(flights, dep_delay, carrier)
## # 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:
select(flights, carrier, everything())
## # 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:
select(flights, year:day)
## # 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.
select(flights, -year)
## # 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
.
select(flights, contains("delay"))
## # 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”
Som är numeriska
Döp om
dep_delay
tillförsenad_avgång
3.4 %>%
kallad “the pipe”
Används för att länka ihop flera uttryck i R.
ctrl + shift + m
(i Windows) ochctrl + command + m
(Mac)
%>%
flights filter(month == 2, arr_time == 830) %>%
select(dest, year, month, day, arr_time)
## # A tibble: 9 x 5
## dest year month day arr_time
## <chr> <int> <int> <int> <int>
## 1 ORD 2013 2 2 830
## 2 DTW 2013 2 4 830
## 3 CLT 2013 2 6 830
## 4 BNA 2013 2 13 830
## 5 BNA 2013 2 18 830
## 6 ATL 2013 2 24 830
## 7 MIA 2013 2 25 830
## 8 CLT 2013 2 26 830
## 9 CLT 2013 2 28 830
3.5 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.
%>%
flights mutate(beer_time = dep_delay - arr_delay)
## # 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>
mutate()
kan användas för att slå ihop variabler
%>%
flights mutate(date = paste(year, month, day, sep = "-")) %>%
select(year, month, day, date)
## # A tibble: 336,776 x 4
## year month day date
## <int> <int> <int> <chr>
## 1 2013 1 1 2013-1-1
## 2 2013 1 1 2013-1-1
## 3 2013 1 1 2013-1-1
## 4 2013 1 1 2013-1-1
## 5 2013 1 1 2013-1-1
## 6 2013 1 1 2013-1-1
## 7 2013 1 1 2013-1-1
## 8 2013 1 1 2013-1-1
## 9 2013 1 1 2013-1-1
## 10 2013 1 1 2013-1-1
## # … with 336,766 more rows
I mutate()
kan du även använda funktioner såsom mean()
.
%>%
flights mutate(mean_delay = mean(dep_delay, na.rm = T)) %>%
select(year, month, day, mean_delay)
## # A tibble: 336,776 x 4
## year month day mean_delay
## <int> <int> <int> <dbl>
## 1 2013 1 1 12.6
## 2 2013 1 1 12.6
## 3 2013 1 1 12.6
## 4 2013 1 1 12.6
## 5 2013 1 1 12.6
## 6 2013 1 1 12.6
## 7 2013 1 1 12.6
## 8 2013 1 1 12.6
## 9 2013 1 1 12.6
## 10 2013 1 1 12.6
## # … with 336,766 more rows
3.5.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:
mutate(flights, försenad = if_else(dep_delay > 5, "försenad", "ej 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 <chr>
3.5.2 case_when()
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(
< 0 ~ "före tid",
dep_delay == 0 ~ "i tid",
dep_delay > 0 ~ "försenad")) dep_delay
## # 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.5.3 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.5.4 Övningar
Skapa en variabel med
dep_delay
minus medelvärdet fördep_delay
Rangordna flygens distans med
dense_rank()
. Hur hanterar den distanser är lika långa? Vilka fler rankingfunktioner skulle du kunna använda? Se?dense_rank()
Skapa en variabel som anger om flyget går på våren, hösten, vintern eller sommaren med
case_when()
3.6 Summarise
Ofta vill man summera variabler för att få ut intressant information. Exempelvis vill vi här kanske veta en rad medelvärden.
%>%
flights summarise(
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)
)
## # A tibble: 1 x 3
## mean_air_time mean_dep_delay mean_arr_delay
## <dbl> <dbl> <dbl>
## 1 151. 12.6 6.90
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()
.
%>%
flights group_by(dest) %>%
summarise(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)) %>%
arrange(desc(mean_arr_delay))
## `summarise()` ungrouping output (override with `.groups` argument)
## # A tibble: 105 x 4
## dest mean_air_time mean_dep_delay mean_arr_delay
## <chr> <dbl> <dbl> <dbl>
## 1 CAE 93.2 35.6 41.8
## 2 TUL 178. 34.9 33.7
## 3 OKC 193. 30.6 30.6
## 4 JAC 264. 26.5 28.1
## 5 TYS 97.7 28.5 24.1
## 6 MSN 123. 23.6 20.2
## 7 RIC 54.0 23.6 20.1
## 8 CAK 64.0 20.8 19.7
## 9 DSM 149. 26.2 19.0
## 10 GRR 97 19.5 18.2
## # … with 95 more rows
I summarise()
kan du använda en rad olika funktioner såsom sum()
för summeringar, n()
för antal rader, median()
för median etc.
%>%
flights group_by(dest) %>%
summarise(
n_rows = n(),
sum_air_time = sum(air_time, na.rm = T),
median_air_time = median(air_time, na.rm = T)) %>%
arrange(desc(sum_air_time))
## `summarise()` ungrouping output (override with `.groups` argument)
## # A tibble: 105 x 4
## dest n_rows sum_air_time median_air_time
## <chr> <int> <dbl> <dbl>
## 1 LAX 16174 5258470 328
## 2 SFO 13331 4553684 345
## 3 ORD 17283 1914833 114
## 4 ATL 17215 1901410 112
## 5 MCO 14082 1882381 133
## 6 FLL 12055 1811271 151
## 7 LAS 5997 1795662 301
## 8 MIA 11728 1775327 152
## 9 DFW 8738 1667341 198
## 10 DEN 7266 1623626 225
## # … with 95 more rows
3.6.1 count()
Du kan i summarise()
räkna antalet observationer med funktionen n()
.
%>%
flights group_by(carrier) %>%
summarise(count = n())
Men istället för att göra det här kan du använda funktionen count()
%>%
flights group_by(carrier) %>%
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.2 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:
sample_n(flights, 10)
## # 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 3 21 1153 1200 -7 1452 1510
## 2 2013 9 15 735 740 -5 1034 1055
## 3 2013 7 3 2035 2028 7 2346 2341
## 4 2013 11 30 1211 1215 -4 1414 1445
## 5 2013 6 13 1548 1520 28 1835 1805
## 6 2013 5 23 912 920 -8 1231 1225
## 7 2013 4 19 1025 1030 -5 1239 1248
## 8 2013 12 12 1126 1130 -4 1348 1342
## 9 2013 9 13 1326 1329 -3 1604 1625
## 10 2013 12 16 954 1000 -6 1324 1335
## # … 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.1%
sample_frac(flights, 0.001)
## # 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 30 811 815 -4 933 935
## 2 2013 12 6 NA 1300 NA NA 1605
## 3 2013 11 3 1317 1259 18 1511 1501
## 4 2013 12 11 1453 1259 114 1805 1614
## 5 2013 1 23 1139 1015 84 1250 1131
## 6 2013 7 23 1903 1830 33 2300 2155
## 7 2013 5 25 2143 1940 123 2251 2100
## 8 2013 9 10 1657 1700 -3 1941 2000
## 9 2013 3 9 737 740 -3 1022 1044
## 10 2013 12 18 2352 2359 -7 441 440
## # … 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.2.1 Övningar
- Vilken flygplats har högst medelvärde förförseningar från flygplatsen?
- Vilken flygplats tar emot minst flyg?
3.6.3 Övning - väv ihop allt du lärt dig
- 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.