In this
In this exercice we will practice a bit of R, exploring data from the Game of thrones series with the dplyr and sf libraries and we will visualize them using the ggplot2 library. The tabular data used was collected by Jeffrey Lancaster and can be found this project. The spatial data was created by ESRI and is available [here](https://www.arcgis.com/home/item.html?id=43d03779288048bfb5d3c46e4bc4ccb0?]. To start you can clone the repository https://github.com/comeetie/got to retrieve all the necessary data.
read_csv() preferably from readr library for a better data type recognition.
str and summary functions on the different tables to understand their structures and relationships.
nrow, ncol or dim to know the dimensions of the data.frame. Use the names function to know the names of the columns and the %in% operator or the intersect function for example to find common variables.
[1] 12114 2
[1] "sceneId"
name sex house killedBy
Length:587 Length:587 Length:587 Length:587
Class :character Class :character Class :character Class :character
Mode :character Mode :character Mode :character Mode :character
image
Length:587
Class :character
Mode :character
tibble [587 × 5] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
$ name : chr [1:587] "Addam Marbrand" "Adrack Humble" "Aeron Greyjoy" "Aerys Targaryen" ...
$ sex : chr [1:587] "male" "male" "male" "male" ...
$ house : chr [1:587] NA NA "Greyjoy" NA ...
$ killedBy: chr [1:587] NA NA NA NA ...
$ image : chr [1:587] NA NA "https://images-na.ssl-images-amazon.com/images/M/MV5BNzI5MDg0ZDAtN2Y2ZC00MzU1LTgyYjQtNTBjYjEzODczZDVhXkEyXkFqcG"| __truncated__ NA ...
- attr(*, "spec")=
.. cols(
.. name = col_character(),
.. sex = col_character(),
.. house = col_character(),
.. killedBy = col_character(),
.. image = col_character()
.. )
sum function.
[1] 376
sum function as above, but select the correct rows using a boolean vector constructed using the id episode column.
table and sort functions
Jon Snow Daenerys Targaryen Arya Stark Sandor Clegane
12 11 10 9
Cersei Lannister
7
which.max.
# A tibble: 1 x 9
sceneStart sceneEnd location subLocation episodeId duration nbc sceneId nbdeath
<time> <time> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
1 45'58" 56'59" The Crownl… Outside King's… 73 661 18 3795 0
arrange,desc and head.
# A tibble: 1 x 9
sceneStart sceneEnd location subLocation episodeId duration nbc sceneId nbdeath
<time> <time> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
1 45'58" 56'59" The Crownl… Outside King's… 73 661 18 3795 0
left_join function to join the scenes and appearences tables.
# A tibble: 18 x 10
sceneStart sceneEnd location subLocation episodeId duration nbc sceneId nbdeath name
<time> <time> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <chr>
1 45'58" 56'59" The Cro… Outside Ki… 73 661 18 3795 0 Tyri…
2 45'58" 56'59" The Cro… Outside Ki… 73 661 18 3795 0 Grey…
3 45'58" 56'59" The Cro… Outside Ki… 73 661 18 3795 0 Samw…
4 45'58" 56'59" The Cro… Outside Ki… 73 661 18 3795 0 Edmu…
5 45'58" 56'59" The Cro… Outside Ki… 73 661 18 3795 0 Arya…
6 45'58" 56'59" The Cro… Outside Ki… 73 661 18 3795 0 Bran…
7 45'58" 56'59" The Cro… Outside Ki… 73 661 18 3795 0 Sans…
8 45'58" 56'59" The Cro… Outside Ki… 73 661 18 3795 0 Brie…
9 45'58" 56'59" The Cro… Outside Ki… 73 661 18 3795 0 Davo…
10 45'58" 56'59" The Cro… Outside Ki… 73 661 18 3795 0 Gend…
11 45'58" 56'59" The Cro… Outside Ki… 73 661 18 3795 0 Yara…
12 45'58" 56'59" The Cro… Outside Ki… 73 661 18 3795 0 Robi…
13 45'58" 56'59" The Cro… Outside Ki… 73 661 18 3795 0 Yohn…
14 45'58" 56'59" The Cro… Outside Ki… 73 661 18 3795 0 Dorn…
15 45'58" 56'59" The Cro… Outside Ki… 73 661 18 3795 0 Lord…
16 45'58" 56'59" The Cro… Outside Ki… 73 661 18 3795 0 Lord…
17 45'58" 56'59" The Cro… Outside Ki… 73 661 18 3795 0 Lord…
18 45'58" 56'59" The Cro… Outside Ki… 73 661 18 3795 0 Lord…
group_by and summarize with the function n().
# A tibble: 26 x 2
location nbsc
<chr> <int>
1 The Crownlands 1252
2 The North 888
3 North of the Wall 342
4 The Wall 309
5 The Riverlands 301
6 Meereen 168
7 Braavos 103
8 The Vale 54
9 Dorne 49
10 The Reach 40
# … with 16 more rows
filter function to target the relevant rows.
# A tibble: 0 x 2
# … with 2 variables: location <chr>, nbsc <int>
sum function during the aggragation and the subLocation feature.
# A tibble: 97 x 2
subLocation nbd
<chr> <dbl>
1 King's Landing 74
2 Winterfell 60
3 <NA> 51
4 Castle Black 41
5 The Twins 12
6 The Haunted Forest 9
7 The Wall 9
8 Craster's Keep 8
9 The Wolfswood 8
10 Dragonstone 6
# … with 87 more rows
sumfunction during the aggregation and join with the scenes and episodes table to aggregate at the episode level.
appearances %>%filter(name=="Jon Snow") %>%
left_join(scenes) %>% left_join(episodes) %>%
group_by(name,episodeId,episodeTitle) %>%
summarise(screenTime=sum(duration)) %>%
arrange(desc(screenTime)) %>% head(1)# A tibble: 1 x 4
# Groups: name, episodeId [1]
name episodeId episodeTitle screenTime
<chr> <dbl> <chr> <dbl>
1 Jon Snow 73 The Iron Throne 2526
appearances %>% left_join(appearances,by=c("sceneId"="sceneId")) %>%
filter(name.x!=name.y) %>%
group_by(name.x,name.y) %>%
summarise(nbs=n()) %>%
arrange(desc(nbs))# A tibble: 8,472 x 3
# Groups: name.x [576]
name.x name.y nbs
<chr> <chr> <int>
1 Daenerys Targaryen Drogon 172
2 Drogon Daenerys Targaryen 172
3 Daenerys Targaryen Jorah Mormont 148
4 Jorah Mormont Daenerys Targaryen 148
5 Jon Snow Tormund Giantsbane 145
6 Tormund Giantsbane Jon Snow 145
7 Lord Varys Tyrion Lannister 141
8 Tyrion Lannister Lord Varys 141
9 Davos Seaworth Jon Snow 136
10 Jon Snow Davos Seaworth 136
# … with 8,462 more rows
appearances %>% left_join(appearances,by=c("sceneId"="sceneId")) %>%
filter(name.x!=name.y) %>%
left_join(scenes %>% select(sceneId,duration)) %>%
group_by(name.x,name.y) %>%
summarise(commonTime=sum(duration)) %>%
arrange(desc(commonTime))# A tibble: 8,472 x 3
# Groups: name.x [576]
name.x name.y commonTime
<chr> <chr> <dbl>
1 Daenerys Targaryen Jorah Mormont 12923
2 Jorah Mormont Daenerys Targaryen 12923
3 Lord Varys Tyrion Lannister 10764
4 Tyrion Lannister Lord Varys 10764
5 Davos Seaworth Jon Snow 10380
6 Jon Snow Davos Seaworth 10380
7 Daenerys Targaryen Missandei 9924
8 Missandei Daenerys Targaryen 9924
9 Jon Snow Tormund Giantsbane 9352
10 Tormund Giantsbane Jon Snow 9352
# … with 8,462 more rows
group_by and a summary and then use the pivot_wider function of the tidyr library to transform the result into a wide format and fill in the missing values with zeros.
rownames.
as.matrix and rowSums
dist calculate the manhatan distance between each line of the previous matrix. Then perform a hierarchical clustering with this distance matrix and display the result. You should get a figure similar to the following one :
geom_line
geom_bar but specify that no stats should be claculated with the option stat='identity' and geom_area.
geom_line and prepare a vector of seasons start time for the labels. Use scale_x_continuous and scale_y_continuous to change the axes labels.
# nombre de morts cumulé et temps passé
deaths = scenes %>% select(nbdeath,duration,location,episodeId) %>%
mutate(t=cumsum(duration),tdeath=cumsum(nbdeath))
# instant de changement de saison
# ? lag
season_t = episodes %>% mutate(ld=lag(total_duration)) %>%
mutate(ld=if_else(is.na(ld),0,ld), td = cumsum(ld)) %>%
filter(episodeNum==1) %>% pull(td)
# geom_line + labels personalisés
ggplot(deaths) + geom_line(aes(x=t/3600,y=tdeath)) +
scale_x_continuous("",expand = c(0,0),breaks = season_t/3600,
labels = paste("Saison",1:8),)+
scale_y_continuous("Nombre de morts cumulés", expand=c(0,0))+
theme_bw()+
theme(axis.text.x=element_text(angle=90))+
ggtitle("Evolution du nombre de mort au cours du temps")geom_point
geom_text and use custom scales and theme.
labels = scenes_stats %>% filter(duration_max>400|nb_scenes>200)
ggplot(scenes_stats,aes(x=nb_scenes,y=duration_max,col=factor(seasonNum)))+
geom_point(aes(size=nbdeath))+
geom_text(data=labels,aes(label=episodeTitle),vjust=-0.6)+
scale_x_continuous("Nombre de scène",limits = c(0,280))+
scale_y_continuous("Durée de la scène la plus longue",limits = c(100,800))+
scale_color_brewer("Saison",palette ="Spectral")+
guides(colour = "legend", size = "legend")+
theme_bw()labels = scenes %>% filter(duration>400)
ggplot(scenes %>% left_join(episodes))+
geom_boxplot(aes(x=factor(episodeId),y=duration,fill=seasonNum))+
geom_text(data=labels ,aes(x=factor(episodeId),y=duration,label=subLocation),hjust = "right",vjust="top")+
xlab("N° épisode")+
ylab("Durée des scènes (min)")+
ggtitle("Répartition des durées des scènes par épisodes")+
theme_bw()Build a table containing for each character and each season the time its screen time. Filter this table to keep only the characters that appear for more than one hour over the seasons. Reorder the levels of the name factor so that the levels are sorted in ascending order of appearance time.
Make a stacked bar-plot of this data identical to the following figure. Use color-brewer to find the palette used.screenTimePerSeasons = appearances %>% left_join(scenes) %>%
left_join(episodes) %>%
group_by(name,seasonNum) %>%
summarise(screenTime=sum(duration)) %>%
arrange(desc(screenTime))
screenTimeTotal = screenTimePerSeasons %>%
group_by(name) %>%
summarise(screenTimeTotal=sum(screenTime))
mainCharacters = screenTimeTotal %>%
filter(screenTimeTotal>60*60) %>%
arrange(screenTimeTotal) %>%
mutate(nameF=factor(name,levels = name))
data = screenTimePerSeasons %>% left_join(mainCharacters) %>% filter(!is.na(nameF))
ggplot(data)+
geom_bar(aes(y=nameF,x=screenTime/60,fill=factor(seasonNum,level=8:1)),stat="identity")+
scale_fill_brewer("Saison",palette = "Spectral")+theme_bw()+
geom_text(data=mainCharacters,aes(y=nameF,x=screenTimeTotal/60+5,label=paste(round(screenTimeTotal/60),'min')),hjust = "left")+
scale_x_continuous("Temps d'apparition (min)",breaks = seq(0,750,by=120),limits = c(0,780),expand = c(0,1))+
ylab("")+ggtitle("Temps d'apparition cumulé par personnage et saison")data/GoTRelease directory as shapefile files with the sf libraries and load them in data-frames with explicit names, you will specify during the import that the coordinate system is (comparable with) the wgs-84 system whose crs code is 4326. Observe the different tables created: dimensions, variables, type of geometry, metadata.
st_read function and the `crs agurment and the classic data.frames functions nrow, dim, summary,…
library(sf)
library(tidyr)
library(ggplot2)
locations=st_read("./data/GoTRelease/Locations.shp",crs=4326)Reading layer `Locations' from data source `/home/come/Projets/got/data/GoTRelease/Locations.shp' using driver `ESRI Shapefile'
Simple feature collection with 247 features and 5 fields
geometry type: POINT
dimension: XY
bbox: xmin: 5.140883 ymin: -34.58818 xmax: 87.984 ymax: 37.21249
geographic CRS: WGS 84
Reading layer `Lakes' from data source `/home/come/Projets/got/data/GoTRelease/Lakes.shp' using driver `ESRI Shapefile'
Simple feature collection with 19 features and 3 fields
geometry type: POLYGON
dimension: XY
bbox: xmin: 8.288085 ymin: -16.38318 xmax: 85.85195 ymax: 45.10014
geographic CRS: WGS 84
Reading layer `Continents' from data source `/home/come/Projets/got/data/GoTRelease/Continents.shp' using driver `ESRI Shapefile'
Simple feature collection with 3 features and 2 fields
geometry type: POLYGON
dimension: XY
bbox: xmin: 0.9011003 ymin: -42.00216 xmax: 91.99359 ymax: 49.10222
geographic CRS: WGS 84
Reading layer `Land' from data source `/home/come/Projets/got/data/GoTRelease/Land.shp' using driver `ESRI Shapefile'
Simple feature collection with 2 features and 2 fields
geometry type: MULTIPOLYGON
dimension: XY
bbox: xmin: 0.9011003 ymin: -42.00216 xmax: 91.99359 ymax: 49.10222
geographic CRS: WGS 84
Reading layer `Wall' from data source `/home/come/Projets/got/data/GoTRelease/Wall.shp' using driver `ESRI Shapefile'
Simple feature collection with 1 feature and 2 fields
geometry type: LINESTRING
dimension: XY
bbox: xmin: 16.39357 ymin: 34.79226 xmax: 20.71819 ymax: 35.19238
geographic CRS: WGS 84
Reading layer `Islands' from data source `/home/come/Projets/got/data/GoTRelease/Islands.shp' using driver `ESRI Shapefile'
Simple feature collection with 86 features and 3 fields
geometry type: MULTIPOLYGON
dimension: XY
bbox: xmin: 5.433233 ymin: -36.04357 xmax: 67.70794 ymax: 37.58262
geographic CRS: WGS 84
Reading layer `Political' from data source `/home/come/Projets/got/data/GoTRelease/Political.shp' using driver `ESRI Shapefile'
Simple feature collection with 12 features and 3 fields
geometry type: MULTIPOLYGON
dimension: XY
bbox: xmin: 0.9011003 ymin: -11.40838 xmax: 26.29015 ymax: 49.10222
geographic CRS: WGS 84
Reading layer `Landscape' from data source `/home/come/Projets/got/data/GoTRelease/Landscape.shp' using driver `ESRI Shapefile'
Simple feature collection with 37 features and 5 fields
geometry type: MULTIPOLYGON
dimension: XY
bbox: xmin: 5.942558 ymin: -41.92678 xmax: 91.91442 ymax: 47.14478
geographic CRS: WGS 84
Reading layer `Roads' from data source `/home/come/Projets/got/data/GoTRelease/Roads.shp' using driver `ESRI Shapefile'
Simple feature collection with 21 features and 4 fields
geometry type: LINESTRING
dimension: XY
bbox: xmin: 6.540938 ymin: -24.64828 xmax: 67.18459 ymax: 34.89038
geographic CRS: WGS 84
Reading layer `Rivers' from data source `/home/come/Projets/got/data/GoTRelease/Rivers.shp' using driver `ESRI Shapefile'
Simple feature collection with 74 features and 4 fields
geometry type: MULTILINESTRING
dimension: XY
bbox: xmin: 6.054601 ymin: -36.23881 xmax: 78.73064 ymax: 42.82271
geographic CRS: WGS 84
st_distance function to calculate distances in m between locations of size5. Which cities are the closest? The farthest ones?
cities = locations %>% filter(size==5)
dists = st_distance(cities)
cities$name[which(dists==max(dists),arr.ind = TRUE)[1,]][1] "Qarth" "White Harbor"
[1] "Tolos" "Elyria"
st_join to make a spatial join between the location table and the kingdoms table (political).
CastlesPerKingdoms= st_join(locations,kingdoms) %>%
filter(type=="Castle") %>%
st_drop_geometry() %>%
count(ClaimedBy)
CastlesPerKingdoms ClaimedBy n
1 Arryn 12
2 Baratheon 14
3 Greyjoy 2
4 Lannister 13
5 Martell 17
6 Night's Watch 2
7 Stark 13
8 Targaryen 7
9 Tully 12
10 Tyrell 16
11 Wildlings 1
12 <NA> 5
st_covers .
sapply` andlapply`.
castles_cover = st_covers(kingdoms,locations %>% filter(type=="Castle"))
kingdoms$nbcastles = sapply(castles_cover,length)
kingdoms %>% arrange(desc(nbcastles))Simple feature collection with 12 features and 4 fields
geometry type: MULTIPOLYGON
dimension: XY
bbox: xmin: 0.9011003 ymin: -11.40838 xmax: 26.29015 ymax: 49.10222
geographic CRS: WGS 84
First 10 features:
id name ClaimedBy nbcastles geometry
1 7 Dorne Martell 17 MULTIPOLYGON (((10.07742 -9...
2 12 The Reach Tyrell 16 MULTIPOLYGON (((7.605566 -2...
3 8 Stormlands Baratheon 14 MULTIPOLYGON (((17.98872 -4...
4 5 The North Stark 13 MULTIPOLYGON (((10.6842 31....
5 10 The Westerlands Lannister 13 MULTIPOLYGON (((11.96501 11...
6 2 Riverlands Tully 12 MULTIPOLYGON (((17.46128 4....
7 9 The Vale Arryn 12 MULTIPOLYGON (((19.00333 18...
8 11 Crownsland Targaryen 7 MULTIPOLYGON (((24.62625 7....
9 4 Bran's Gift Night's Watch 2 MULTIPOLYGON (((15.17952 34...
10 6 The Iron Islands Greyjoy 2 MULTIPOLYGON (((8.194052 13...
st_intersection function should make your job easier, but don’t forget the st_area function to calculate areas and the basic functions of dplyr.
st_intersection(kingdoms,landscapes) %>%
mutate(area=st_area(geometry)) %>%
count(ClaimedBy,wt=area) %>%
st_drop_geometry() %>%
arrange(desc(n)) ClaimedBy n
1 Stark 1.304682e+12 [m^2]
2 Wildlings 6.000348e+11 [m^2]
3 Arryn 4.988246e+11 [m^2]
4 Martell 4.640324e+11 [m^2]
5 Lannister 3.983993e+11 [m^2]
6 Baratheon 3.724850e+11 [m^2]
7 Tully 1.388066e+11 [m^2]
8 Tyrell 7.842595e+10 [m^2]
9 Night's Watch 4.558375e+10 [m^2]
10 Targaryen 2.750644e+10 [m^2]
data/GoTRelease/ScenesLocations.shp will give you the locations of the places referenced in the scene table and you will use the lag function of dplyr.
lag function after a group_by per character to build a column containing the previous location of the character. Make a double join with the scenes_locations table and use the st_distance function using the by_element option to calculate the distance between two scenes and finally sum it all up with a sum.
main_char= c("Jon Snow", "Tyrion Lannister","Daenerys Targaryen","Sansa Stark","Cersei Lannister","Arya Stark")
scenes_locations=st_read("./data/GoTRelease/ScenesLocations.shp",crs=4326)Reading layer `ScenesLocations' from data source `/home/come/Projets/got/data/GoTRelease/ScenesLocations.shp' using driver `ESRI Shapefile'
Simple feature collection with 26 features and 2 fields
geometry type: POINT
dimension: XY
bbox: xmin: 4.143957 ymin: -34.58818 xmax: 87.984 ymax: 38.61921
geographic CRS: WGS 84
distance_characters = scenes %>% left_join(appearances) %>%
filter(name %in% main_char) %>%
group_by(name) %>%
mutate(previous_location=lag(location)) %>%
filter(location!=previous_location) %>%
left_join(scenes_locations)%>%
left_join(scenes_locations,by=c("previous_location"="location")) %>%
mutate(dist=st_distance(geometry.x,geometry.y,by_element = TRUE)) %>%
summarise(total_dist=sum(as.numeric(dist),na.rm=TRUE)/1000)
distance_characters # A tibble: 6 x 2
name total_dist
<chr> <dbl>
1 Arya Stark 12728.
2 Cersei Lannister 4709.
3 Daenerys Targaryen 61185.
4 Jon Snow 39059.
5 Sansa Stark 11569.
6 Tyrion Lannister 28375.
lag function of dplyr.
summary` function to group these points into a multipoint that will keep the order (thedo_union` option should be of interest to you). Convert these points into lines using the st_cast function and calculate the length of these lines.
distance_characters = scenes %>% left_join(appearances) %>%
filter(name %in% main_char) %>%
left_join(scenes_locations) %>%
st_as_sf() %>%
group_by(name) %>% summarise(do_union=FALSE) %>% sf::st_cast("LINESTRING") %>% mutate(dist=as.numeric(st_length(geometry))/1000)
distance_characters Simple feature collection with 6 features and 2 fields
geometry type: LINESTRING
dimension: XY
bbox: xmin: 4.143957 ymin: -34.58818 xmax: 87.984 ymax: 38.61921
geographic CRS: WGS 84
# A tibble: 6 x 3
name geometry dist
* <chr> <LINESTRING [°]> <dbl>
1 Arya Stark (14.89991 25.02354, 14.89991 25.02354, 14.89991 25.02354, 14.8999… 12728.
2 Cersei Lannis… (21.22862 5.640294, 14.89991 25.02354, 14.89991 25.02354, 14.8999… 4709.
3 Daenerys Targ… (31.12798 4.632835, 31.12798 4.632835, 31.12798 4.632835, 31.1279… 61185.
4 Jon Snow (14.89991 25.02354, 14.89991 25.02354, 14.89991 25.02354, 14.8999… 39059.
5 Sansa Stark (14.89991 25.02354, 14.89991 25.02354, 14.89991 25.02354, 14.8999… 11569.
6 Tyrion Lannis… (14.89991 25.02354, 14.89991 25.02354, 14.89991 25.02354, 14.8999… 28375.
geom_sf` andgeom_sf_text` and be inspired by this map:
ggplot theme and the graph coordinate system options with `coord_sf.
colforest="#c0d7c2"
colriver="#7ec9dc"
colriver="#87cdde"
colland="ivory"
borderland = "ivory3"
ggplot()+geom_sf(data=land,fill=colland,col=borderland,size=0.1)+
geom_sf(data=islands,fill=colland,col="ivory3")+
geom_sf(data=landscapes %>% filter(type=="forest"),fill=colforest,col=colforest)+
geom_sf(data=rivers,col=colriver)+
geom_sf(data=lakes,col=colriver,fill=colriver)+
geom_sf(data=wall,col="black",size=1)+
geom_sf_text(data= locations %>% filter(size>4,name!='Tolos'),aes(label=name),size=2.5,family="Palatino", fontface="italic")+
theme_minimal()+coord_sf(expand = 0,ndiscr = 0)+
theme(panel.background = element_rect(fill = colriver,color=NA)) +
labs(title = "GoT",caption = "Etiennne Côme, 2020",x="",y="")data//GoTRelease/ScenesLocations.shp and join it with the previous table. Finally make a map with proportional symbols to visualize these data.
FALSE Reading layer `ScenesLocations' from data source `/home/come/Projets/got/data/GoTRelease/ScenesLocations.shp' using driver `ESRI Shapefile'
FALSE Simple feature collection with 26 features and 2 fields
FALSE geometry type: POINT
FALSE dimension: XY
FALSE bbox: xmin: 4.143957 ymin: -34.58818 xmax: 87.984 ymax: 38.61921
FALSE geographic CRS: WGS 84
st_as_sf containing a column name with the names of the 6 main characters of the series “Jon Snow”, “Tyrion Lannister”, “Daenerys Targaryen”, “Sansa Stark”, “Cersei Lannister”, “Arya Stark” and an identical geometry column for all characters containing the union of all land and island polygons.
st_geometry pour extraire les géométrie uniquement et st_union plusieurs fois pour combiner les polygones en un unique multi-polygone. Enfin, utilisez st_as_sf pour convertir une data.frame avec une colone geometrie et une colonne name en data.frame spatiale.
main_char= c("Jon Snow", "Tyrion Lannister","Daenerys Targaryen","Sansa Stark","Cersei Lannister","Arya Stark")
landpol = st_union(st_geometry(land))
islandpol = st_union(st_geometry(islands))
backpol=st_union(landpol,islandpol)
background = st_as_sf(data.frame(name=main_char,geometry=rep(backpol,6)))facet_wrap with the two previously built data.frame.
ggplot()+geom_sf(data=background,color=borderland,fill=colland)+
geom_sf(data=loc_time_mc%>% filter(!is.na(duration)),aes(size=duration/60,color=name))+
geom_sf_text(data=loc_time_mc%>% filter(duration>60*60),aes(label=location),color="#000000",vjust="bottom",family="Palatino", fontface="italic")+
coord_sf(expand = 0,ndiscr = 0)+
scale_color_discrete(guide="none")+
scale_size_area("Durée (min) :",max_size = 12,breaks=c(30,60,120,240))+
facet_wrap(~name)+
theme(panel.background = element_rect(fill = colriver,color=NA),
text = element_text(family="Palatino",face = "bold",size = 14),
legend.key = element_rect(fill="#ffffff"),
) +
labs(title = "Temps de présence des personnage principaux",caption = "@comeetie, 2020",x="",y="")reproducibility
R version 4.0.0 (2020-04-24)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 20.04 LTS
Matrix products: default
BLAS: /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.9.0
LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.9.0
locale:
[1] LC_CTYPE=fr_FR.UTF-8 LC_NUMERIC=C LC_TIME=fr_FR.UTF-8
[4] LC_COLLATE=fr_FR.UTF-8 LC_MONETARY=fr_FR.UTF-8 LC_MESSAGES=fr_FR.UTF-8
[7] LC_PAPER=fr_FR.UTF-8 LC_NAME=C LC_ADDRESS=C
[10] LC_TELEPHONE=C LC_MEASUREMENT=fr_FR.UTF-8 LC_IDENTIFICATION=C
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] sf_0.9-6 ggplot2_3.3.2 tidyr_1.1.2 dplyr_1.0.2 readr_1.4.0 knitr_1.30
loaded via a namespace (and not attached):
[1] Rcpp_1.0.5 RColorBrewer_1.1-2 pillar_1.4.6 compiler_4.0.0
[5] unilur_0.4.0.9000 class_7.3-17 tools_4.0.0 digest_0.6.27
[9] evaluate_0.14 lifecycle_0.2.0 tibble_3.0.4 gtable_0.3.0
[13] pkgconfig_2.0.3 rlang_0.4.8 DBI_1.1.0 cli_2.1.0
[17] rstudioapi_0.11 yaml_2.2.1 xfun_0.19 e1071_1.7-4
[21] withr_2.3.0 stringr_1.4.0 generics_0.1.0 vctrs_0.3.4
[25] hms_0.5.3 classInt_0.4-3 grid_4.0.0 tidyselect_1.1.0
[29] glue_1.4.2 R6_2.5.0 fansi_0.4.1 rmarkdown_2.1
[33] farver_2.0.3 purrr_0.3.4 magrittr_1.5 units_0.6-7
[37] scales_1.1.1 ellipsis_0.3.1 htmltools_0.5.0 assertthat_0.2.1
[41] colorspace_1.4-1 labeling_0.4.2 KernSmooth_2.23-17 utf8_1.1.4
[45] stringi_1.5.3 munsell_0.5.0 lwgeom_0.2-3 crayon_1.3.4