Kapitel 4 Explorativ dataanalys
4.1 Vad är Explorativ Dataanalys?
En kreativ iterativ process där man ställer frågor/gör hypoteser om sin data och sedan utforskar dem
Mera konkret kan det beskrivas som
- Formulera en hypotes
- Transformera din data - om nödvändigt
- Visualisera din data (vårt fokus idag)
- Modellera - om nödvändigt
- Formulera nya hypoteser
Mindset inte formel!
4.1.1 Exempel på basala frågor/hypoteser
Frågeställningar kan vara vaga!
Vad för data innehåller de olika kolonnerna?
Hur ser Datans kvalitét ut? e.g missing values, felaktiga tabellvärden, duplicerade värden
Finns det outliers?
Medelvärde, spridning
4.1.2 Hur gör man i R?
R har basfunktionalitet som kan användas för att snabbt få en numerisk överblick datan t.ex
summary()
och head()
summary(iris)
## Sepal.Length Sepal.Width Petal.Length Petal.Width
## Min. :4.300 Min. :2.000 Min. :1.000 Min. :0.100
## 1st Qu.:5.100 1st Qu.:2.800 1st Qu.:1.600 1st Qu.:0.300
## Median :5.800 Median :3.000 Median :4.350 Median :1.300
## Mean :5.843 Mean :3.057 Mean :3.758 Mean :1.199
## 3rd Qu.:6.400 3rd Qu.:3.300 3rd Qu.:5.100 3rd Qu.:1.800
## Max. :7.900 Max. :4.400 Max. :6.900 Max. :2.500
## Species
## setosa :50
## versicolor:50
## virginica :50
##
##
##
head(iris)
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1 5.1 3.5 1.4 0.2 setosa
## 2 4.9 3.0 1.4 0.2 setosa
## 3 4.7 3.2 1.3 0.2 setosa
## 4 4.6 3.1 1.5 0.2 setosa
## 5 5.0 3.6 1.4 0.2 setosa
## 6 5.4 3.9 1.7 0.4 setosa
4.1.3 Hur gör man i R?
R har även mer avancerade verktyg:
- dlookr
, ta fram rapport för datakvalitét
skimr
, snabb explorativ analys (som vi kommer använda idag)
skim(iris)
4.2 Datavisualisering
Grunden i explorativ dataanalys
Visualisering är grundläggande för att människor ska kunna få en överblick av data
4.2.1 Varför visualisera?
Anscombe quartet - Dataset skapat av Francis Anscombe 1973
## observation set x y
## 1 1 I 10 8.04
## 2 1 II 10 9.14
## 3 1 III 10 7.46
## 4 1 IV 8 6.58
## 5 2 I 8 6.95
## 6 2 II 8 8.14
## 7 2 III 8 6.77
## 8 2 IV 8 5.76
## 9 3 I 13 7.58
## 10 3 II 13 8.74
4.2.2 Vad är det första vi gör?
## # A tibble: 4 x 5
## set x_mean y_mean x_sd y_sd
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 I 9 7.50 3.32 2.03
## 2 II 9 7.50 3.32 2.03
## 3 III 9 7.5 3.32 2.03
## 4 IV 9 7.50 3.32 2.03
Ser bra ut!
4.2.3 Steg 2: anpassar en linjär modell
%>%
anscombe_tidy nest(observation, x, y) %>%
mutate(model = map(data, ~lm(y ~ x, data = .x)),
tidy = map(model, broom::tidy)) %>%
unnest(tidy) %>%
filter(term == "x") %>%
select(set, estimate, std.error, statistic)
## Warning: All elements of `...` must be named.
## Did you want `data = c(observation, x, y)`?
## # A tibble: 4 x 4
## set estimate std.error statistic
## <chr> <dbl> <dbl> <dbl>
## 1 I 0.500 0.118 4.24
## 2 II 0.5 0.118 4.24
## 3 III 0.500 0.118 4.24
## 4 IV 0.500 0.118 4.24
Ser inte ut som att det är någon skillnad mellan grupperna
Men…
## `geom_smooth()` using formula 'y ~ x'
Statistiska mått kan gömma mycket av sanningen!
4.3 Datasaurus Dozen
Modern variant av Anscombe - skapat av Alberto Cairo
library(datasauRus)
%>%
datasaurus_dozen group_by(dataset) %>%
summarise(x_mean = mean(x), y_mean = mean(y),
x_sd = sd(x), y_sd = sd(y),
corr = cor(x,y))
## `summarise()` ungrouping output (override with `.groups` argument)
## # A tibble: 13 x 6
## dataset x_mean y_mean x_sd y_sd corr
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 away 54.3 47.8 16.8 26.9 -0.0641
## 2 bullseye 54.3 47.8 16.8 26.9 -0.0686
## 3 circle 54.3 47.8 16.8 26.9 -0.0683
## 4 dino 54.3 47.8 16.8 26.9 -0.0645
## 5 dots 54.3 47.8 16.8 26.9 -0.0603
## 6 h_lines 54.3 47.8 16.8 26.9 -0.0617
## 7 high_lines 54.3 47.8 16.8 26.9 -0.0685
## 8 slant_down 54.3 47.8 16.8 26.9 -0.0690
## 9 slant_up 54.3 47.8 16.8 26.9 -0.0686
## 10 star 54.3 47.8 16.8 26.9 -0.0630
## 11 v_lines 54.3 47.8 16.8 26.9 -0.0694
## 12 wide_lines 54.3 47.8 16.8 26.9 -0.0666
## 13 x_shape 54.3 47.8 16.8 26.9 -0.0656
Datasaurus Dozen
ggplot(datasaurus_dozen, aes(x=x, y=y))+
geom_point()+
theme_minimal() +
facet_wrap(~dataset)
Eller som animering:
library(datasauRus)
library(ggplot2)
library(gganimate)
ggplot(datasaurus_dozen, aes(x=x, y=y))+
geom_point()+
theme_minimal() +
transition_states(dataset, 3, 1) +
ease_aes('cubic-in-out')
4.4 Workflow för nytt dataset
Börja alltid med visualisering, särskilt om du ska göra modellering
explorativ visualisering är en iterativ process
Börjar övergripande sedan mera specialiserade beroende på hur dina hypoteser/frågor utvecklas
Gör alltid explorativ analys med ett programmeringsspråk
Det gör att din analys finns dokumenterad
Du kan dela med den till andra
Den är reproducerbar och kan granskas
Saker du bör undvika: BI-verktyg för explorativ analys och Excel.
4.5 Gapminder
Vi har fått ett dataset
gapminder
och egentligen inga andra uppgifter och vi vill förstå detVi börjar med att snabbt kolla på datan med
head()
library(gapminder)
head(gapminder)
## # A tibble: 6 x 6
## country continent year lifeExp pop gdpPercap
## <fct> <fct> <int> <dbl> <int> <dbl>
## 1 Afghanistan Asia 1952 28.8 8425333 779.
## 2 Afghanistan Asia 1957 30.3 9240934 821.
## 3 Afghanistan Asia 1962 32.0 10267083 853.
## 4 Afghanistan Asia 1967 34.0 11537966 836.
## 5 Afghanistan Asia 1972 36.1 13079460 740.
## 6 Afghanistan Asia 1977 38.4 14880372 786.
- Undersöker med hjälp av
summary()
/skim()
summary(gapminder)
## country continent year lifeExp
## Afghanistan: 12 Africa :624 Min. :1952 Min. :23.60
## Albania : 12 Americas:300 1st Qu.:1966 1st Qu.:48.20
## Algeria : 12 Asia :396 Median :1980 Median :60.71
## Angola : 12 Europe :360 Mean :1980 Mean :59.47
## Argentina : 12 Oceania : 24 3rd Qu.:1993 3rd Qu.:70.85
## Australia : 12 Max. :2007 Max. :82.60
## (Other) :1632
## pop gdpPercap
## Min. :6.001e+04 Min. : 241.2
## 1st Qu.:2.794e+06 1st Qu.: 1202.1
## Median :7.024e+06 Median : 3531.8
## Mean :2.960e+07 Mean : 7215.3
## 3rd Qu.:1.959e+07 3rd Qu.: 9325.5
## Max. :1.319e+09 Max. :113523.1
##
library(skimr)
skim(gapminder)
4.5.1 Datapunkter per land?
%>% filter(country == "Sweden") %>% arrange(year) gapminder
## # A tibble: 12 x 6
## country continent year lifeExp pop gdpPercap
## <fct> <fct> <int> <dbl> <int> <dbl>
## 1 Sweden Europe 1952 71.9 7124673 8528.
## 2 Sweden Europe 1957 72.5 7363802 9912.
## 3 Sweden Europe 1962 73.4 7561588 12329.
## 4 Sweden Europe 1967 74.2 7867931 15258.
## 5 Sweden Europe 1972 74.7 8122293 17832.
## 6 Sweden Europe 1977 75.4 8251648 18856.
## 7 Sweden Europe 1982 76.4 8325260 20667.
## 8 Sweden Europe 1987 77.2 8421403 23587.
## 9 Sweden Europe 1992 78.2 8718867 23880.
## 10 Sweden Europe 1997 79.4 8897619 25267.
## 11 Sweden Europe 2002 80.0 8954175 29342.
## 12 Sweden Europe 2007 80.9 9031088 33860.
4.5.1.1 Naturlig fråga: Hur påverkar ekonomisk utveckling den förväntande livslängden i ett land?
För att undersöka den här frågan så vill vi göra en visualisering med hjälp av ggplot2
Då behöver vi först
4.6 Grammar of grahics
4.6.1 1. Data
För att minska mängden data kollar vi bara på ett år
<- gapminder %>%
data filter(year == 1972)
ggplot(data)
4.6.2 2. Aesthetics
Vi behöver
mappa
data till visualiseringen. Vi mappar data tillaestethics
i visualiseringen. Enaesthetic
kan vara exempelvisx
-axeln ellery
-axeln.För att svara på vår fråga kan vi exempelvis mappa
gdpPercap
tillx
-axeln ochlifeExp
tilly
-axeln
ggplot(data = data, aes(x = gdpPercap, y = lifeExp))
4.6.3 3. Geometriska objekt
Vi behöver geometriska objekt som representerar data, exempelvis punkter, linjer eller staplar.
I ggplot2 kallas dessa för geoms
, exempelvis:
geom_point()
: punkter,
geom_line()
: linjer,
geom_bar()
: staplar
ggplot(data = data, aes(x = gdpPercap, y = lifeExp)) +
geom_point()
Det verkar finnas ett samband, kan vi förstå mera?
Mer aesthetics
<- ggplot(data = data,
p aes(x = gdpPercap,
y = lifeExp,
color = continent)) +
geom_point()
4.6.3.1 Storlek ~ invånare
ännu mer aesthetics
ggplot(data = data,
aes(x = gdpPercap,
y = lifeExp,
color = continent,
size = pop)) +
geom_point()
4.6.4 4. Skala
Vilken skala ska axlarna i grafen ha?
ggplot(data = data, aes(x = gdpPercap, y = lifeExp,
size = pop, color = continent)) +
geom_point() +
scale_y_continuous() + ## Default value
scale_x_continuous()
4.6.5 GDP per capita är skevt fördelad
Vanligt i variabler som motsvarar pengar
ggplot(data, aes(x = gdpPercap)) +
geom_density()
4.6.5.1 Logaritmisk skala
Genom att ta logaritmen kan vi justera för den skeva fördelningen
ggplot(data, aes(x = gdpPercap)) +
geom_density() +
scale_x_log10() ##
ggplot(data = data, aes(x = gdpPercap,
y = lifeExp,
size = pop,
color = continent)) +
geom_point() +
scale_x_log10()
##<4 Hans Roslings berömda visualisering
library(gganimate)
library(gapminder)
ggplot(gapminder, aes(gdpPercap, lifeExp, size = pop, colour = continent)) +
geom_point(alpha = 0.7) +
#scale_colour_manual(values = country_colors) +
scale_size(range = c(2, 12)) +
scale_x_log10() +
guides(color= guide_legend(), size=FALSE) +
theme_light() +
labs(title = 'Year: {frame_time}',
x = 'GDP per capita',
y = 'life expectancy') +
transition_time(year) +
ease_aes('linear')
4.6.6 5. Statistiska beräkningar
För att kvantifiera sammanbandet mera kan vi också lägga till statistiska beräkningar till grafen
ggplot(data = data, aes(x = gdpPercap,
y = lifeExp,
size = pop,
color = continent)) +
geom_point() +
scale_x_log10() +
stat_smooth(method = "lm")
## `geom_smooth()` using formula 'y ~ x'
## Warning in qt((1 - level)/2, df): NaNs produced
## Warning in max(ids, na.rm = TRUE): no non-missing arguments to max; returning -
## Inf
Nu beräknas statistik per grupp. Det är eftersom att vi specificerat i vår
aes()
iggplot()
.Vi kan flytta
aes()
till våra geometriska objekt om vi vill beräkna statistik för hela gruppen.
ggplot(data = data, aes(x = gdpPercap, y = lifeExp)) +
geom_point(aes(size = pop, color = continent)) +
scale_x_log10() +
stat_smooth(method = "lm")
## `geom_smooth()` using formula 'y ~ x'
4.6.7 6. Facets
Vi kan också dela upp grafen i flera visualiseringar
ggplot(data = data, aes(x = gdpPercap,
y = lifeExp,
size = pop,
color = continent)) +
geom_point() +
scale_x_log10() +
stat_smooth(method = "lm") +
facet_wrap(~continent)
## `geom_smooth()` using formula 'y ~ x'
## Warning in qt((1 - level)/2, df): NaNs produced
## Warning in max(ids, na.rm = TRUE): no non-missing arguments to max; returning -
## Inf
Vi kan också specificera skalorna för varje subplot
ggplot(data = data, aes(x = gdpPercap,
y = lifeExp,
size = pop,
color = continent)) +
geom_point() +
scale_x_log10() +
stat_smooth(method = "lm") +
facet_wrap(~continent, scales = "free")
## `geom_smooth()` using formula 'y ~ x'
## Warning in qt((1 - level)/2, df): NaNs produced
## Warning in max(ids, na.rm = TRUE): no non-missing arguments to max; returning -
## Inf
4.6.8 7. Koordinatsystem
- Ett sista lager vi skulle kunna använda för att ändra vår graf
- Exempelvis Kartesiskt eller Polärt
- Polärt för exempelvis cirkeldiagram
4.6.9 Grammar of graphics
R Paketet som har använts heter ggplot2
och det bygger på en variant av The Grammar of Graphics och består av de 7 beståndsdelar vi precis gått igenom
.footnote[ Wickham, H (2010), “A layered Grammar of Graphics”, Journal of Computational and Graphical Statistics, vol. 19, no. 1, pp. 3–28,]
Data
Aesthetics
Geometric Objects
Scale
Statistics
Facets
Coordinate systems
(8.) Labels, titlar, legends
Som kan manipuleras för att skapa de visualiseringar vi vill ha
4.7 Gapminder - fortsättning
Vi såg att det fanns en outlier i gdpPercap
per lifeExp
Vilket land är det?
%>% arrange(desc(gdpPercap)) data
## # A tibble: 142 x 6
## country continent year lifeExp pop gdpPercap
## <fct> <fct> <int> <dbl> <int> <dbl>
## 1 Kuwait Asia 1972 67.7 841934 109348.
## 2 Switzerland Europe 1972 73.8 6401400 27195.
## 3 Saudi Arabia Asia 1972 53.9 6472756 24837.
## 4 United States Americas 1972 71.3 209896000 21806.
## 5 Libya Africa 1972 52.8 2183877 21011.
## 6 Canada Americas 1972 72.9 22284500 18971.
## 7 Norway Europe 1972 74.3 3933004 18965.
## 8 Denmark Europe 1972 73.5 4991596 18866.
## 9 Netherlands Europe 1972 73.8 13329874 18795.
## 10 Bahrain Asia 1972 63.3 230800 18269.
## # … with 132 more rows
Är det en utveckling som håller i sig?
<- gapminder %>%
kuwait_data filter(country == "Kuwait")
%>%
kuwait_data ggplot(aes(x=year, y=gdpPercap)) +
geom_line(color='red') + scale_color_identity()
I jämförelse med utveckingen i resten av toppländerna 1972?
<- data %>% top_n(11, gdpPercap) %>%
top_countries filter( country!= 'Kuwait') %>%
pull(country)
top_countries
## [1] Bahrain Canada Denmark Germany Libya
## [6] Netherlands Norway Saudi Arabia Switzerland United States
## 142 Levels: Afghanistan Albania Algeria Angola Argentina Australia ... Zimbabwe
<- gapminder %>%
top_mean filter(country %in% top_countries) %>%
group_by(year) %>%
summarise(gdp_mean = mean(gdpPercap))
## `summarise()` ungrouping output (override with `.groups` argument)
top_mean
## # A tibble: 12 x 2
## year gdp_mean
## <int> <dbl>
## 1 1952 9468.
## 2 1957 11271.
## 3 1962 13393.
## 4 1967 17146.
## 5 1972 20673.
## 6 1977 23406.
## 7 1982 23799.
## 8 1987 24323.
## 9 1992 25740.
## 10 1997 27633.
## 11 2002 29947.
## 12 2007 33389.
<- kuwait_data %>% add_column(
data_added_mean "mean" = top_mean$gdp_mean)
%>%
data_added_mean ggplot(aes(x = year)) +
geom_line(aes(y = gdpPercap), color = 'red') +
geom_line(aes(y = mean), color = 'gray') +
scale_color_identity()
4.8 EDA är en nyfiken process utan slut!
Det finns i princip alltid mera saker man skulle kunna undersöka som:
Hur ser utvecklingen ut om vi istället för att undersöka BNP per kapita, undersöker totala BNP per land?
Om vi utesluter Kuwait som en outlier 1972?
Om vi inför en annan gruppering?
etc..
4.8.1 Det ni ska ta med er idag är inte de specifika sakerna vi har undersökt, utan ett mindset!
4.9 Länkar till resurser
R for Data Science - fantastisk bok som har bra material om alling Data Science
Visual Vocabulary - Financial Times referensmaterial för visualiseringar
ggplot2 - dokumentation för ggplot2
kaggle - Hemsida med AI/ML tävlingar och källa till gratis dataset
stack overflow - Forum för programmeringsfrågor, där svar på nästan alla problem man stöter på finns
4.10 Övningar Explorativ dataanalys
Datan vi använder idag kommer från Hemnet!
library(tidyverse) # Innehåller många mindre paket bl.a ggplot2
library(scales) # Färghanteringspaket
library(gapminder) # Datasetet gapminder
library(hrbrthemes) # Teman till ggplot2
<- read_csv("https://raw.githubusercontent.com/Ferrologic/ds-program-block2/master/data/hemnet_data.csv")
hem
hem
## # A tibble: 99,838 x 15
## sold_date final_price square_m_price type area city sq_m rooms fee
## <date> <dbl> <dbl> <chr> <chr> <chr> <dbl> <dbl> <dbl>
## 1 2019-01-11 2800000 56000 bost… järv… solna 50 2 3087
## 2 2019-01-11 1280000 18003 bost… östr… malmö 711 3 4346
## 3 2019-01-11 7250000 76316 frit… sote… sote… 95 6 NA
## 4 2019-01-11 2130000 38727 bost… väll… stoc… 55 2 3838
## 5 2019-01-11 950000 11176 fril… cent… kil 85 3 NA
## 6 2019-01-11 2195000 39909 bost… edsä… soll… 55 2 3208
## 7 2019-01-11 2900000 30851 par/… bran… hani… 94 3 NA
## 8 2019-01-11 4200000 46154 bost… minn… stoc… 91 4 4641
## 9 2019-01-11 2825000 49045 bost… erik… göte… 576 2 2875
## 10 2019-01-11 1995000 29556 bost… stoc… stoc… 675 2 5218
## # … with 99,828 more rows, and 6 more variables: add_area_sqm <dbl>,
## # perc_change <dbl>, list_price <dbl>, price_diff <dbl>, month <chr>,
## # weekday <chr>
Vi kan börja med att använda skim()
från skimr
på vårt dataset.
library(___)
skim(___)
## Error: <text>:1:9: unexpected input
## 1: library(_
## ^
Det var mycket information. Men vi kan försöka plocka ut några delar.
Hur många rader och kolumner har datasetet?
Vad för typ av data är kolumnen area
?
I vilken kolumn saknas det flest värden?
Men vad innehåller egentligen kolumnerna area
, type
? För att svara på det så kan vi titta på några rader av dataset med R:s inbyggda funktion head()
head(___)
## Error: <text>:1:6: unexpected input
## 1: head(_
## ^
Säg att det företag du jobbar på endast är intresserad av Stockholm, Malmö och Göteborg då börjar vi med att endast titta på de försäljningar som gjorts där:
Om du känner att du hellre vill undersöka några andra städer så är det bara att skriva in dem istället, men försäkra dig om att städerna finns med genom att exempelvis använda hem %>% filter(city == 'din stad')
eller hem[hem$city == 'din stad',]
.
<- hem %>% filter(city %in% c('stockholm', 'malmö', ___)) hem_storstad
## Error: <text>:1:66: unexpected input
## 1: hem_storstad <- hem %>% filter(city %in% c('stockholm', 'malmö', _
## ^
Hur har de slutgiltiga priserna i storstäderna sett ut?
ggplot(___,
aes(x = ___)) +
geom_density()
## Error: <text>:1:8: unexpected input
## 1: ggplot(_
## ^
Är det nån skillnad mellan städerna? Det kan vi undersöka med hjälp av färg och en ridgeplot:
library(ggridges)
ggplot(___,
aes(x = ___,
y = city,
color = ___,
fill = city)) + geom_density_ridges()
## Error: <text>:2:8: unexpected input
## 1: library(ggridges)
## 2: ggplot(_
## ^
Vill vi göra en lättare jämförelse mellan städerna kan vi använda geom_density()
istället och färg. Notera användandet av alpha
och jämför med det tidigare kommandot. Det är också värt att notera användandet av parametern alpha
, som styr hur genomskinliga de olika densiteterna är.
%>% ggplot(aes(x = ___,
___ color = city,
fill = city)) +
geom_density(alpha=0.5)
## Error: <text>:1:1: unexpected input
## 1: _
## ^
Som i gapminder
-exemplet från presentationen så är fördelningen för final price skev.
Igen så kan vi använda en logaritmisk skala på x axeln scale_x_log10()
för att motverka detta.
<- hem %>% filter(city %in% c('stockholm', 'malmö', "göteborg"))
hem_storstad
%>% ggplot(aes(x = final_price,
hem_storstad color = city, fill = city)) +
geom_density(alpha = 0.5) +
scale_x_log10()
Vad kan vi se för skillnader mellan fördelingen av slutpriser mellan de städerna? Vilken stad är dyrast? Vad är det vanligaste priset ungefär? Är det någon stad som är mer olik de andra?
Det går självklart att fortsätta att ställa mera frågor och undersöka dem, men nu kommer resten av övningarna att fokusera på att introducera flera sorters visualiseringar!
4.11 Fördelningar
I de flesta fall är vi intresserade av fördelningar. De vanligaste typerna av visualiserings för fördelingar är dessa:
Densitetsdiagram:
library(gapminder)
ggplot(gapminder, aes(x = gdpPercap)) +
geom_density()
Histogram:
ggplot(gapminder, aes(x = gdpPercap)) +
geom_histogram()
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
Boxplots:
ggplot(gapminder, aes(x = continent, y = gdpPercap)) +
geom_boxplot()
Fioldiagram:
ggplot(gapminder, aes(x = continent, y = gdpPercap)) +
geom_violin()
Ridgediagram:
library(ggridges)
ggplot(gapminder, aes(x = gdpPercap, y = continent, fill = continent)) +
geom_density_ridges() +
theme_ridges() +
theme(legend.position = "none")
## Picking joint bandwidth of 1650
För att direkt jämföra grupperna går även ett densitetsdiagram med färg att använda
ggplot(gapminder, aes(x = gdpPercap, color = continent)) +
geom_density(aes(fill = continent, alpha = 0.7))
4.11.1 Skalor och fördelningar
I verkligheten är data sällan normalt fördelad. Med den underliggande statistiska processen kan ofta vara det. Därför kan det vara klokt, om data är skevt fördelat, att testa att använda en annan skala på data. Det finns flera olika sätt att transformera data till en annan skala men ett av de vanligaste är att ta logaritmen.
Nedan skalar vi x-axeln med log10()
, som är den logaritm vi oftast använder i “verkligheten”.
ggplot(gapminder, aes(x = gdpPercap)) +
geom_histogram() +
scale_x_log10()
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
4.11.2 Övningar - Fördelning
Nu är det din tur att prova på de här graferna på hemnetdatan hem
.
Hur ser fördelningen ut för final_price
?
ggplot(aes(_)) +
geom_
## Error: <text>:1:12: unexpected input
## 1: ggplot(aes(_
## ^
Hur ser fördelningen ut för respektive type
? Nedan använder du dig av en ridge-plot.
library(ggridges)
ggplot(hem, aes(x = final_price, y = _, fill = type)) +
geom_density_ridges() +
theme_ridges() +
theme(legend.position = _) +
scale_x_continuous(labels = scales::number)
## Error: <text>:2:38: unexpected input
## 1: library(ggridges)
## 2: ggplot(hem, aes(x = final_price, y = _
## ^
Boxplot är en annan värdefull visualiseringstyp. Den kalkylerar även outliers, som är de svarta prickarna. Outliers är här definierade som Q3 + 1.5*IQR, d.v.s. den tredje kvartilen + 1.5 gånger avståndet mellan kvartil 1 och kvartil 3.
- Visualisera slutpris per bostadstyp
- Notera att vi använder
scales
iscale_x_continuous()
för att få snyggare formatering på x-axlen.scales
har också formateringsalternativ för procent, kr/$/€ med mera.
ggplot(hem, aes(x = final_price, y = _, fill = _)) +
geom_boxplot() +
theme(legend.position = "none") +
scale_x_continuous(labels = scales::number_format(suffix = "kr"))
## Error: <text>:1:38: unexpected input
## 1: ggplot(hem, aes(x = final_price, y = _
## ^
4.12 Korrelation
Visualisera relationen mellan list_price
och final_price
.
- Vad är dina
aesthetics
? - Vilken
geom_
använder du? - Passar skalan?
- Finns det någon passande statistic för att visuellt beskriva relationen?
ggplot(_, aes(x = _, y = _)) +
+
geom_ stat_
## Error: <text>:1:8: unexpected input
## 1: ggplot(_
## ^
4.13 Pimp my plot!
Vi kan addera titlar och data-etiketter med labs()
.
<- ggplot(mtcars, aes(mpg, hp, color = am)) +
p geom_point() +
labs(title = "Min titel",
x = "Min x-axel",
y = "Min y-axel",
subtitle = "Min subtitle",
caption = "Källa: Min caption",
color = "Legend-titel")
p
4.14 Vi kan ändra tema med theme_...
+ theme_minimal() p
Utgå från relationen mellan slutpris och listpris. Ändra labs och lägg till ett tema.
OBS Det finns en uppsjö av olika teman. Exempelvis i paketen hrbrthemes
, ggthemes
, ggthemr
m.m. Du kan också skapa dina egna teman exempelvis med företagsfont och färger. Testa gärna exempelvis theme_economist() och theme_solarized_2()
library(ggthemes)
ggplot(hem, aes(x = list_price, y = final_price)) +
geom_point() +
stat_smooth() +
labs(title = "",
x = "",
y = "",
subtitle = "",
caption = "") +
theme_
## Error in eval(expr, envir, enclos): object 'theme_' not found
4.15 Andra aesthetics
- Utgå från din visualisering av relationen mellan utropspris och slutpris
- Mappa vår aesthetic
color
till en numerisk variabel, exempelvisfee
. - Vad händer om vår data har stora outliers? (testa att mappa
color
till sq_m)
ggplot(hem, aes(x = list_price,
y = final_price,
color = ___)) +
geom_point() +
stat_smooth()
## Error: <text>:3:25: unexpected input
## 2: y = final_price,
## 3: color = _
## ^
4.16 Diskreta variabler
- Utgå från din visualisering av relationen mellan utropspris och slutpris
- Mappa vår aesthetic
color
till en kategorisk variabel, notera att kategoriska variabler med fler än 30 kategorier kommer att bli svåra att visualisera. Se exempelvis city och area, som du därmed bör undvika. - Om det är en kategorisk variabel som är numerisk behöver du ändra den med
as.factor()
ggplot(hem, aes(x = list_price,
y = final_price,
color = ...)) +
geom_point() +
stat_smooth()
## Error in ggplot.default(hem, aes(x = list_price, y = final_price, color = ...)): '...' used in an incorrect context
4.17 Facets
- Visualisera fördelningen per bostadstyp med sub-plots istället
- Hur hanterar du x-axeln? Finns det något sätt att göra den snyggare?
- För att hantera långa labels i
facet_wrap()
kan du använda funktionenlabeller
ochlabel_wrap_gen(10)
.
ggplot(hem, aes(final_price)) +
geom_histogram() +
scale_x_log10() +
facet_wrap(~___, labeller = labeller(type = label_wrap_gen(10)), scales = "free")
## Error: <text>:4:15: unexpected input
## 3: scale_x_log10() +
## 4: facet_wrap(~_
## ^
4.18 Barcharts på aggregerade tabeller
Inte sällan har vi aggregerade tabeller som vi vill visualisera.
<- gapminder %>%
gap_continent group_by(continent) %>%
summarise(mean_gdp_per_cap = mean(gdpPercap))
## `summarise()` ungrouping output (override with `.groups` argument)
gap_continent
## # A tibble: 5 x 2
## continent mean_gdp_per_cap
## <fct> <dbl>
## 1 Africa 2194.
## 2 Americas 7136.
## 3 Asia 7902.
## 4 Europe 14469.
## 5 Oceania 18622.
4.18.1 geom_col()
geom_bar()
används när vi vill veta antalet rader per kategorigeom_col()
används på färdiga tabeller- Sorterar efter bokstavsordning på kategorier
%>%
gap_continent ggplot(aes(x = continent, y = mean_gdp_per_cap)) +
geom_col()
Ibland har vi många kategorier, då kan vi bara byta plats på x
och y
%>%
gap_continent ggplot(aes(y = continent, x = mean_gdp_per_cap)) +
geom_col()
4.18.2 Hur fördelar sig kvadratmeterpris per bostadstyp?
Ta fram en aggregerad tabell med genomsnittligt kvadratmeterpris per bostadstyp
Vilken funktion använder du för att kalkylera genomsnitt? Ha fördelningen i åtanke
Visualisera med
geom_col()
<- hem %>%
tbl_type group_by(type) %>%
summarise(median_sq_m_price = median(square_m_price, na.rm = T))
## `summarise()` ungrouping output (override with `.groups` argument)
ggplot(tbl_type, aes(y = type, x = _)) +
geom_col()
## Error: <text>:1:36: unexpected input
## 1: ggplot(tbl_type, aes(y = type, x = _
## ^
4.19 Sortera kategorier
- Ofta vill vi sortera en kategori vi viusaliserar i fallande eller stigande ordning
- Då kan vi bara använda
reorder(x, X = sum)
%>%
gap_continent ggplot(aes(y = reorder(continent, mean_gdp_per_cap), x = mean_gdp_per_cap)) +
geom_col()
4.20 Sortera din bar-chart efter medianpris
ggplot(tbl_type,
aes(y = reorder(type, ___),
x = median_sq_m_price)) +
geom_col()
## Error: <text>:2:35: unexpected input
## 1: ggplot(tbl_type,
## 2: aes(y = reorder(type, _
## ^
4.21 Tidsserier
Vi har någon form av tidsserie som vi vill visualisera. Oftast har vi då en tidskomponent, exempelvis dag eller månad. I vår hemnet-data har vi datum.
- Kalkylera genomsnittligt försäljningspris per dag och visualisera
- Vilken geom använder du?
- Vilken skala använder du?
%>%
hem group_by(sold_date) %>%
summarise(median_sq_m_price = median(square_m_price, na.rm = T)) %>%
ggplot(aes(_, y = median_sq_m_price)) +
geom_()
## Error: <text>:4:14: unexpected input
## 3: summarise(median_sq_m_price = median(square_m_price, na.rm = T)) %>%
## 4: ggplot(aes(_
## ^
————————- OM DU HAR TID ÖVER ————————- Kolla på den här listan och gör det som verkar mest intressant!
Fri uppgift som går ut på att undersöka ett annat dataset själv och utforska det och se vad du hittar.
Lite mera om tidsserier och hur du kan ändra granulariteten på dina tidserier
Testa på enkel interaktivitet i dina grafer
Läsa på från en rekommenderad lista
Undersöka själv. Du kan självklart fortsätta att undersäka Hemnet datan! Men om du inte vill det så är lite exempel på dataset som du kan använda:
iris
- inbyggt dataset i r som innehåller mätdata om ett par olika blomarter.iris
finns alltid tillgängligt i r och är bara att kalla på:
mtcars
- inbyggt dataset i r som inehåller mätdata om 32 bilmodeller från 1974.
mtcars
finns alltid tillgängligt på samma sätt som iris
Pokemon - Dataset som innehåller statistik om alla Pokemon genom tiderna. Hämtat från Kaggl
Laddas med pokemon <- read_csv('data/pokemon.csv)
Temp - Globala temperaturer per land och datum från 1743 till 2013 mätt en gång i månaden.
Laddas med temp <- read_csv('data/GlobalTemp.csv')
Covid-19 - Dataset hämtat från Our World In Data (https://ourworldindata.org/coronavirus-source-data), 15/11/2020,
som får sin data från the European Center for Disease Control.
Innehåller daglig data från hela världen.
Det här datasetet är större och svårare att hantera än de andra.
Datasetet laddas med cov <- read_csv('data/covid19-ECDC.csv')
## Börja undersöka här!
# iris
# mtcars
# pokemon <- read_csv('data/pokemon.csv')
# temp <- read_csv('data/GlobalTemp.csv')
# cov <- read_csv('data/covid19-ECDC.csv')
- Mer stabila tidsserier
Inte sällan vill vi ha lite mindre granulära tidsserier än det vi hade tidigare, exempelvis per vecka eller månad
Vi kan då använda antigen
lubridate
för att få fram exempelvisvecka
ochår
Eller
tsibble
för att få framyearweek
elleryearmonth
.Ladda
tsibble
ochlubridate
Skapa en kolumn som representera vecka
En som representerar år
En som representerar år-vecka med
tsibble::yearweek()
Visualisera per år-vecka
Visualisera per vecka och sätt
color = år
library(lubridate)
##
## Attaching package: 'lubridate'
## The following objects are masked from 'package:base':
##
## date, intersect, setdiff, union
library(tsibble)
##
## Attaching package: 'tsibble'
## The following object is masked from 'package:lubridate':
##
## interval
<- hem %>%
weekly_sales mutate(
year = as.factor(year(sold_date)),
week = week(sold_date),
yearweek = yearweek(sold_date)
)
<- weekly_sales %>%
p group_by(yearweek) %>%
summarise(median_sq_m_price = median(square_m_price, na.rm = T)) %>%
ggplot(aes(yearweek, median_sq_m_price)) +
geom_line()
## `summarise()` ungrouping output (override with `.groups` argument)
p
- Interaktivitet
Med paketet plotly
kan du ta ett ggplot2
-objekt och göra om det till en interaktiv graf, som kräver en hemsida.
library(plotly)
##
## Attaching package: 'plotly'
## The following object is masked from 'package:ggplot2':
##
## last_plot
## The following object is masked from 'package:stats':
##
## filter
## The following object is masked from 'package:graphics':
##
## layout
<- hem %>%
plot group_by(sold_date) %>%
summarise(median_sq_m_price = median(square_m_price, na.rm = T)) %>%
ggplot(aes(sold_date, y = median_sq_m_price)) +
geom_line()
## `summarise()` ungrouping output (override with `.groups` argument)
ggplotly(plot)
- Läslista
4.22 Grammar of Graphics - Artikel om the grammar of graphics som ggplot bygger på
4.23 R for Data Science
- Både kapitel 3 - Data Visualisation och Kapitel 7 - Exploratory Data Analysis är väldigt relevanta
4.24 ggplot2 extensions
- Det finns ett flertal extensions till ggplot
- Gå in och kolla på några på https://exts.ggplot2.tidyverse.org/gallery/
4.25 Shiny
- Ett ramverk för att bygga skräddarsydda applikationer i R
- Har likheter med traditionella BI-verktyg men är Open Source och därmed kostnadsfritt
- Är mer flexibelt än ett traditionellt BI-verktyg - allt du kan göra i HTML kan du göra i Shiny.
- Ett otroligt kraftig verktyg för en Data Scientist - automatisera mera
- Innebär att vi kan paketera analyser som applikationer som användare kan agera med
- Exempelvis ta fram en prognosmodell och låta användare testa att själva ändra paramterar i den, exempelvis vilken typ av säsongsvariation
- https://shiny.rstudio.com/gallery/
- https://shiny.rstudio.com/tutorial/