Skip to content

Commit

Permalink
Merge pull request #109 from Robinlovelace/rev1
Browse files Browse the repository at this point in the history
Rev1
  • Loading branch information
Robinlovelace authored Oct 28, 2017
2 parents 0f76845 + 1616402 commit b880eb8
Show file tree
Hide file tree
Showing 20 changed files with 689 additions and 239 deletions.
102 changes: 58 additions & 44 deletions 01-introduction.Rmd

Large diffs are not rendered by default.

261 changes: 169 additions & 92 deletions 02-spatial-data.Rmd

Large diffs are not rendered by default.

29 changes: 21 additions & 8 deletions 03-attribute-operations.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,14 @@ attributes(methods(class = "sf"))$info %>%

Many of these functions, including `rbind()` (for binding rows of data together) and `$<-` (for creating new columns) were developed for data frames.
A key feature of `sf` objects is that they store spatial and non-spatial data in the same way, as columns in a `data.frame` (the geometry column is typically called `geometry`).

```{block2 type = 'rmdnote'}
The geometry column of `sf` objects is typically called `geometry` but any name can be used.
The following command, for example, creates a geometry column named `g`:
`st_sf(data.frame(n = world$name_long), g = world$geom)`.
This enables geometries imported from spatial databases to have a variety of names such as `wkb_geometry` and `the_geom`.
```

`sf` objects also support `tibble` and `tbl` classes used in the tidyverse, allowing 'tidy' data analysis workflows for spatial data.
Thus **sf** enables the full power of R's data analysis capabilities to be unleashed on geographic data.
Before using these capabilities it's worth re-capping how to discover the basic properties of vector data objects.
Expand Down Expand Up @@ -256,10 +264,6 @@ world8 = dplyr::select(

This generates the same result --- verify this with `identical(world7, world8)` --- in the same number of lines of code, but in a much more confusing way, starting with the function that is called last!

```{block2 type='rmdnote'}
The 'right arrow' `->` operator can be used to make the result be assigned at the end of a chaining process.
```

There are additional advantages of pipes from a communication perspective: they encourage adding comments to self-contained functions and allow single lines *commented-out* without breaking the code.

### Vector attribute aggregation
Expand Down Expand Up @@ -433,7 +437,9 @@ class(left_join4)
```

```{block2 type='rmdnote'}
It is possible to convert a data frame with a geometry list column, such as `left_join4`, into an `sf` object with `st_as_sf()`, as follows: `st_as_sf(left_join4)`.
In most cases the geometry column is only useful in an `sf` object.
The geometry column can only be used for creating maps and spatial operations if R 'knows' it is a spatial object, defined by a spatial package such as **sf**.
Fortunately non-spatial data frames with a geometry list column (like `left_join4`) can be coerced into an `sf` object as follows: `st_as_sf(left_join4)`.
```

<!-- On the other hand, it is also possible to remove the geometry column of `left_join4` using base R functions or `dplyr`. -->
Expand Down Expand Up @@ -466,7 +472,6 @@ For this we need to divide a population column, here `pop`, by an area column ,
Using base R, we can type:

```{r}
data("world")
world_new = world # do not overwrite our original data
world_new$pop_dens = world_new$pop / world_new$area_km2
```
Expand Down Expand Up @@ -557,7 +562,6 @@ The following code recreates the raster dataset used in section \@ref(raster-cla
This demonstrates how the `raster()` function works to create an example raster named `elev` (representing elevations).

```{r, message=FALSE}
library(raster)
elev = raster(nrow = 6, ncol = 6, res = 0.5,
xmn = -1.5, xmx = 1.5, ymn = -1.5, ymx = 1.5,
vals = 1:36)
Expand Down Expand Up @@ -630,7 +634,16 @@ To extract all values or complete rows, you can use `values()` and `getValues()`
For multi-layered raster objects `stack` or `brick`, this will return the cell value(s) for each layer.
For example, `stack(elev, grain)[1]` returns a matrix with one row and two columns --- one for each layer.
<!-- In this example we have used cell ID subsetting, of course, you can also use row-column or coordinate indexing. -->
For multi-layer raster objects another way to subset is with `raster::subset()`, which extracts layers from a raster stack or brick. The `[[` and `$` operators can also be used.
For multi-layer raster objects another way to subset is with `raster::subset()`, which extracts layers from a raster stack or brick. The `[[` and `$` operators can also be used:

```{r, eval = FALSE}
r_stack = stack(elev, grain)
names(r_stack) = c("elev", "grain")
# three ways to extract a layer of a stack
raster::subset(r_stack, "elev")
r_stack[["elev"]]
r_stack$elev
```

Cell values can be modified by overwriting existing values in conjunction with a subsetting operation.
The following code chunk, for example, sets the upper left cell of `elev` to 0:
Expand Down
226 changes: 179 additions & 47 deletions 04-spatial-operations.Rmd

Large diffs are not rendered by default.

41 changes: 24 additions & 17 deletions 05-read-write-plot.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,17 @@ Nowadays, a vast amount of spatial data is available on the internet.
Best of all, much of it is freely available.
You just have to know where to look.
While we cannot provide a comprehensive guide to all available geodata, we point to a few of the most important sources.
Overall, geolibraries and geoportals facilitate the search and download of geodata.
Geolibraries are a very useful data source but often only contain data for a specific locations.
Then you might struggle to find the exact geolibrary matching his or her demands.
Here, geolibraries come to the rescue bundling the information of a collection of geolibraries.
If you are looking for data from all over the world, the [GEOSS portal](http://www.geoportal.org/) might be a good starting point.
We also would like you to point to the [EarthExplorer](https://earthexplorer.usgs.gov/) and the [Copernicus Open Access Hub](https://scihub.copernicus.eu/) for a wide variety of global datasets including multispectral and radar images.
European data is available from the Initiative for spatial information in the European Community ([INSPIRE](http://inspire-geoportal.ec.europa.eu/)).
This [Wikipedia article](https://en.wikipedia.org/wiki/Geoportal) lists a few more interesting geoportals.
Various 'geoportals' (web services providing geographic data such as the geospatial datasets in [Data.gov](https://catalog.data.gov/dataset?metadata_type=geospatial)) are a good place to start, providing a wide range of geographic data.
Geoportals are a very useful data source but often only contain data for a specific locations (see the [Wikipedia page on geoportals](https://en.wikipedia.org/wiki/Geoportal) for a list of geoportals covering many areas of the world).

To overcome this limitation some global geoportals have been developed.
The [GEOSS portal](http://www.geoportal.org/), for example, provides global remote sensing data.
Additional geoportals with global coverage and an emphasis on raster data include the [EarthExplorer](https://earthexplorer.usgs.gov/) and the [Copernicus Open Access Hub](https://scihub.copernicus.eu/).
A wealth of European data is available from the [INSPIRE geoportal](http://inspire-geoportal.ec.europa.eu/).

Typically, geoportals provide an interface that lets you query interactively the existing data (spatial and temporal extent, and product).
However, in this book we encourage you to create reproducible workflows.
Automated data downloads are often possible through simple download calls or specific APIs (e.g., have a look at the Sentinel API), which saves human working time, and allows to easily repeat and update this process in the future.
In many cases data downloads can be scripted via download calls to static URLs or APIs (see the [Sentinel API](https://scihub.copernicus.eu/twiki/do/view/SciHubWebPortal/APIHubDescription) for example), saving time, and enabling others to repeat and update the unglamorous data download process.

Traditionally, files have been stored on servers.
<!-- that's probably not the best example - replace it with something better -->
Expand All @@ -62,7 +61,7 @@ unzip(zipfile = "USA_parks.zip")
usa_parks = st_read("ne_10m_parks_and_protected_lands_area.shp")
```

Specific R packages providing an interface to geolibraries or geoportals are even more user-friendly (Table \@ref(tab:datapackages)).
Specific R packages providing an interface to spatial libraries or geoportals are even more user-friendly (Table \@ref(tab:datapackages)).

<!-- add sentinel2 package as soon as it is published on CRAN https://github.com/IVFL-BOKU/sentinel2-->
```{r datapackages, echo=FALSE}
Expand Down Expand Up @@ -220,7 +219,6 @@ In most cases, as with the ESRI Shapefile (`.shp`) or the `GeoPackage` format (`
`st_read()` guesses the driver based on the file extension, as illustrated for a `.gpkg` file below:

```{r}
library(sf)
vector_filepath = system.file("shapes/world.gpkg", package = "spData")
world = st_read(vector_filepath)
```
Expand Down Expand Up @@ -263,14 +261,25 @@ In these situations, it is possible to add the missing information using the `st
Please refer also to section \@ref(crs-intro) for more information.
```

As a final example, we will show how `st_read()` also reads KML files.
A KML file stores geographic information in XML format - a data format for the creation of web pages and the transfer of data in an application-independent way [@nolan_xml_2014].
Here, we access a KML file from the web.
This file contains more than one layer.
`st_layers()` lists all available layers.
We choose the first layer `Placemarks` and say so with the help of the `layer` parameter in `read_sf()`.

```{r}
url = "https://developers.google.com/kml/documentation/KML_Samples.kml"
st_layers(url)
kml = read_sf(url, layer = "Placemarks")
```

### Raster data

Similar to vector data, raster data comes in many file formats with some of them supporting even multilayer files.
**raster**'s `raster()` command reads in a single layer.

```{r, message=FALSE}
library(raster)
library(spDataLarge)
raster_filepath = system.file("raster/srtm.tif", package = "spDataLarge")
single_layer = raster(raster_filepath)
```
Expand Down Expand Up @@ -356,7 +365,6 @@ This can be done by specifying `GEOMETRY` inside of `layer_options`.
It could be either `AS_XY` for simple point datasets (it creates two new columns for coordinates) or `AS_WKT` for more complex spatial data (one new column is created which contains the well-known-text representation of spatial objects).

```{r, eval=FALSE}
library(spData)
st_write(cycle_hire_xy, "cycle_hire_xy.csv", layer_options = "GEOMETRY=AS_XY")
st_write(world_wkt, "world_wkt.csv", layer_options = "GEOMETRY=AS_WKT")
```
Expand Down Expand Up @@ -447,14 +455,13 @@ save_tmap(tm = tmap_obj, filename = "lifeExp_tmap.png")
<!-- a = plot(world["lifeExp"]) -->
<!-- ``` -->

On the other hand, on can save interactive maps as an HTML file using the `saveWidget()` function from the `htmlwidgets` package:
On the other hand, on can save interactive maps created in the `mapview` package as an HTML file or image using the `mapshot()` function:

<!-- example doesn't work, problem with colors I guess -->
```{r, eval=FALSE}
library(mapview)
library(htmlwidgets)
mapview_obj = mapview(world, zcol = "lifeExp", legend = TRUE)
saveWidget(mapview_obj, file = "my_interactive_map.html")
mapshot(mapview_obj, file = "my_interactive_map.html")
```

## Exercises
Expand Down
2 changes: 2 additions & 0 deletions 06-transform.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -154,3 +154,5 @@ It is hidden from view for most of the time except when the object is printed bu
<!-- ### Shearing -->

<!-- Todo: add content on simplifying using mapshaper and other packages (e.g. sf) -->

### Exercises
3 changes: 1 addition & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,11 @@ Imports:
tabularaster,
tidyverse,
tmap
Remotes: Nowosad/spData
URL: https://github.com/Robinlovelace/geocompr
BugReports: https://github.com/Robinlovelace/geocompr/issues
LazyData: TRUE
RoxygenNote: 6.0.1
Suggests: knitr,
rmarkdown
Remotes: nowosad/spDataLarge,
nowosad/spData
VignetteBuilder: knitr
6 changes: 3 additions & 3 deletions code/02_crs_plot.R
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ p2 = ggplot() +
coord_sf(datum = sf::st_crs(4326)) +
theme(axis.text = element_text(size = 4))

vector_crs = arrangeGrob(p1, p2, nrow = 1)
vector_crs = arrangeGrob(p2, p1, nrow = 1)

ggsave(plot = vector_crs,
filename = "figures/02_vector_crs.png",
Expand All @@ -40,6 +40,6 @@ pr1 = levelplot(new_raster, margin = FALSE, colorkey = FALSE)
pr2 = levelplot(new_raster2, margin = FALSE, colorkey = FALSE)

png(filename = "figures/02_raster_crs.png", width = 950, height = 555)
plot(pr1, split=c(1, 1, 2, 1), more=TRUE)
plot(pr2, split=c(2, 1, 2, 1))
plot(pr2, split=c(1, 1, 2, 1), more=TRUE)
plot(pr1, split=c(2, 1, 2, 1))
dev.off()
2 changes: 2 additions & 0 deletions code/sf_plot.R
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ p_geometrycollection_sf = ggplot() +
)

## combine plot ------------
png("figures/sf-classes.png", height = 600, width = 600)
# Empty grob for spacing
b = nullGrob() # per @baptiste's comment, use nullGrob() instead of rectGrob()

Expand Down Expand Up @@ -240,3 +241,4 @@ vp = viewport(
pushViewport(vp)

mygb(x = c(1, 0.6, 0.6, 0), y = c(1, 0.4, 0.4, 0))
dev.off()
Binary file modified figures/02_raster_crs.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified figures/02_vector_crs.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified figures/sf-classes.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added figures/vector_lonlat.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added figures/vector_projected.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 13 additions & 8 deletions index.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,28 @@ Welcome to **geocompr**, the [website](http://robinlovelace.net/geocompr) of our
## Development {-}

Inspired by the **bookdown** [R package](https://github.com/rstudio/bookdown) we are developing this book in the open.
We decided to make the book open source to encourage contributions, ensure reproducibility and provide access to the material as it evolves.
We decided to make the book open source.
Why?
To encourage contributions, ensure reproducibility and provide access to the material as it evolves.

We're developing the book in four main phases.
We're in phase two and focussed on the application chapters, which we aim to be complete by December.
Drafts of other chapters will be added to this website as the project progresses.

The latest version is hosted at [robinlovelace.net/geocompr](http://robinlovelace.net/geocompr).
This website is kept up-to-date thanks to Travis, a continuous integration (CI) service.
Travis automatically rebuilds the book and finds bugs by reporting the 'build status' after every update.
1. Foundations
2. Basic applications
3. Geocomputation methods
4. Advanced applications

Currently we're working primarily on the second part, which we aim to be complete by December.
New chapters will be added to this website as the project progresses, hosted at [robinlovelace.net/geocompr](http://robinlovelace.net/geocompr) and kept up-to-date thanks to [Travis](https://travis-ci.org/Robinlovelace/geocompr).
Currently the build is:

[![Build Status](https://travis-ci.org/Robinlovelace/geocompr.svg?branch=master)](https://travis-ci.org/Robinlovelace/geocompr)

The version of the book you are reading now was built on `r Sys.Date()` and was built `r if(is_on_travis) "on [Travis](https://travis-ci.org/Robinlovelace/geocompr)" else "locally"`.
**bookdown** makes editing a book as easy as editing a wiki.
To do so, just click on the 'edit me' icon highlighted in the image below.
Which-ever chapter you are looking at, this will take you to the source [R Markdown](http://rmarkdown.rstudio.com/) file hosted on GitHub. If you have a GitHub account, you'll be able to make changes there and submit a pull request. If you do not, it's time to [sign-up](https://github.com/)!
**bookdown** makes editing a book as easy as editing a wiki, provided you have a GitHub account ([sign-up at github.com](https://github.com/)).
Once logged-in to GitHub, clicking on the 'edit me' icon highlighted in the image below will take you to the source [R Markdown](http://rmarkdown.rstudio.com/) where you can make changes:

[![](figures/editme.png)](https://github.com/Robinlovelace/geocompr/edit/master/index.Rmd)

Expand All @@ -61,7 +66,7 @@ if(!require(devtools)) {
devtools::install_github("robinlovelace/geocompr")
```

To build the book locally, clone or [download](https://github.com/Robinlovelace/geocompr/archive/master.zip) the repo and run the following line from the [project](https://github.com/Robinlovelace/geocompr/blob/master/geocompr.Rproj)'s root directory:
To build the book locally, clone or [download](https://github.com/Robinlovelace/geocompr/archive/master.zip) the [geocompr repo](https://github.com/Robinlovelace/geocompr/), open the [geocompr.Rproj project file](https://github.com/Robinlovelace/geocompr/blob/master/geocompr.Rproj) in RStudio and run the following lines:

```{r, eval=FALSE}
bookdown::render_book("index.Rmd") # to build the book
Expand Down
23 changes: 23 additions & 0 deletions preface.Rmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Preface

## Who this book is for and who is it not for

This book is certainly aimed at people with an interest in spatial data analysis with the help of R.
This includes graduate students and researchers from geography, remote sensing and GIScience but also from other backgrounds as diverse as remote sensing, biogeosciences, ecology, forestry, transportation, ... <!-- please add further fields-->
This is the beauty of GIScience as it is applicable to all fields dealing with spatial phenomena.
And even more importantly, GIScience is not only a scientific domain but also used in the public sector and in the business world.
This makes our book, furthermore, interesting to people dealing with urban planning, transportation (logistics) and (geo-)marketing, ... <!-- please add further examples-->
This book also aims at persons with a solid knowledge of GIS technologies who wish to automate their spatial data analysis workflow in a reproducible manner on the command line.

Though we have tried our best to make our book as accessible as possible to a wide audience, people new to R might find it hard at first reading.
People who prefer a GUI-based GIS approach over the command line might find this book only interesting from a conceptual point of view.
Our programming language is R, and though we refer at times to other languages, people with an interest in geoprocessing with Python, Java, C++ or alike should probably look for another book.

<!-- to think about, not sure if needed but then this would be a good place to point out why our book might have advantages over the other books -->
## Justification, context
compare with:
- ASDAR
- An intro to R for spatial analysis and mapping
- Remote Sensing and GIS for ecologists
- Mapping and Environmental and Ecological Statistics with R (not really a competitor, I have ordered a copy, this book is really about modeling, and I would rather prefer the Zuur et al. books over it)
- http://rspatial.org/intr/index.html (haven't read it but might be more suitable for beginners, however, it does not consider sf; additionally, it provides more code than text, and hence, probably less explanations than our book)
Loading

0 comments on commit b880eb8

Please sign in to comment.