Skip to contents

KoboToolbox allows the collection of spatial data through three questions types: geopoint, geotrace and geoshape.

Geopoint:
The geopoint question type captures a single geographic coordinate (latitude and longitude) including altitude and accuracy. This is useful for marking locations, such as homes, schools, or water sources.

Geotrace:
The geotrace question type collects a series of connected geographic coordinates, forming a line. This can be used to map routes, paths, or boundaries.

Geoshape:
A geoshape question type captures a series of geographic coordinates that form a closed polygon. This is useful for defining areas, such as land parcels, agricultural fields, or protected zones.

To utilize these data types, we need to parse them into a GIS friendly format. robotoolbox uses Well-Known Text (WKT), a standard markup language for representing vector geometry, to represent points (geopoint), lines (geotrace) and polygons (geoshape).

Spatial data

The following form provides a simple demonstration of how robotoolbox maps spatial field types.

Survey questions

name type label
point geopoint Record a location
point_description text Describe the recorded location
line geotrace Record a line
line_description text Describe the recorded line
polygon geoshape Record a polygon
polygon_description text Describe the recorded polygon

The form includes three spatial type columns: point, line and polygon.

Loading the project

The aforementioned form, named Spatial data, was uploaded to the server. You can load it from the asset_list of assets.

library(robotoolbox)
library(dplyr)
asset_list <- kobo_asset_list()
uid <- filter(asset_list, name == "Spatial data") |>
  pull(uid)
asset <- kobo_asset(uid)
asset
#> <robotoolbox asset>  a9NCKTJxBPKdy49gX57WL5 
#>   Asset name: Spatial data
#>   Asset type: survey
#>   Asset owner: dickoa
#>   Created: 2023-04-22 11:57:54
#>   Last modified: 2023-04-22 12:01:39
#>   Submissions: 1

We have a single submission, where we recorded one location using a geopoint question, mapped a portion of a road using a geotrace question, and outlined a stadium using a `geoshape`` question.

Extracting the data

From the assets, we can proceed to extract the submissions.

df <- kobo_data(asset)
glimpse(df)
#> Rows: 1
#> Columns: 23
#> $ point                <chr> "14.719783 -17.459261 0 0"
#> $ point_latitude       <dbl> 14.71978
#> $ point_longitude      <dbl> -17.45926
#> $ point_altitude       <dbl> 0
#> $ point_precision      <dbl> 0
#> $ point_wkt            <chr> "POINT (-17.459261 14.719783 0)"
#> $ point_description    <chr> "Jardin Liberte"
#> $ line                 <chr> "14.726129 -17.500409 0 0;14.726253 -17.498993 0 …
#> $ line_wkt             <chr> "LINESTRING (-17.500409 14.726129 0, -17.498993 1…
#> $ line_description     <chr> "Route de la Corniche"
#> $ polygon              <chr> "14.747328 -17.452461 0 0;14.747743 -17.451869 0 …
#> $ polygon_wkt          <chr> "POLYGON ((-17.452461 14.747328 0, -17.451869 14.…
#> $ polygon_description  <chr> "Stade Leopold Sedar Senghor"
#> $ `_id`                <int> 28557821
#> $ uuid                 <chr> "01c7d7250bd84ac9b604199ca98daa84"
#> $ `__version__`        <chr> "v7nQkzvEV64YLAfEQv5prV"
#> $ instanceID           <chr> "uuid:26c66ec5-935a-4220-8902-6de928330122"
#> $ `_xform_id_string`   <chr> "a9NCKTJxBPKdy49gX57WL5"
#> $ `_uuid`              <chr> "26c66ec5-935a-4220-8902-6de928330122"
#> $ `_status`            <chr> "submitted_via_web"
#> $ `_submission_time`   <dttm> 2023-04-22 12:07:29
#> $ `_validation_status` <chr> NA
#> $ `_submitted_by`      <lgl> NA

We can see that we have all of our three columns point, line and polygon. For each of them, we have a corresponding WKT column.

pull(df, point)
#> [1] "14.719783 -17.459261 0 0"
#> attr(,"label")
#> [1] "Record a location"
pull(df, point_wkt)
#> [1] "POINT (-17.459261 14.719783 0)"
#> attr(,"label")
#> [1] "point_wkt"

For geopoint types, robotoolbox also offers columns for latitude, longitude, altitude, and precision.

df |>
  select(starts_with("point_"))
#> # A tibble: 1 × 6
#>   point_latitude point_longitude point_altitude point_precision point_wkt       
#>            <dbl>           <dbl>          <dbl>           <dbl> <chr>           
#> 1           14.7           -17.5              0               0 POINT (-17.4592…
#> # ℹ 1 more variable: point_description <chr>

The line column, derived from the geotrace question, has a corresponding line_wkt column.

pull(df, line)
#> [1] "14.726129 -17.500409 0 0;14.726253 -17.498993 0 0;14.725688 -17.498002 0 0;14.72527 -17.497068 0 0;14.724897 -17.496113 0 0;14.72438 -17.495383 0 0;14.723737 -17.494784 0 0"
#> attr(,"label")
#> [1] "Record a line"
pull(df, line_wkt)
#> [1] "LINESTRING (-17.500409 14.726129 0, -17.498993 14.726253 0, -17.498002 14.725688 0, -17.497068 14.72527 0, -17.496113 14.724897 0, -17.495383 14.72438 0, -17.494784 14.723737 0)"
#> attr(,"label")
#> [1] "line_wkt"

Lastly, polygon_wkt is the WKT column derived from the geoshape question labeled polygon.

pull(df, polygon)
#> [1] "14.747328 -17.452461 0 0;14.747743 -17.451869 0 0;14.747519 -17.451477 0 0;14.747244 -17.451332 0 0;14.746378 -17.451332 0 0;14.745989 -17.451563 0 0;14.745844 -17.451987 0 0;14.746062 -17.45232 0 0;14.74627 -17.452492 0 0;14.747328 -17.452461 0 0"
#> attr(,"label")
#> [1] "Record a polygon"
pull(df, polygon_wkt)
#> [1] "POLYGON ((-17.452461 14.747328 0, -17.451869 14.747743 0, -17.451477 14.747519 0, -17.451332 14.747244 0, -17.451332 14.746378 0, -17.451563 14.745989 0, -17.451987 14.745844 0, -17.45232 14.746062 0, -17.452492 14.74627 0, -17.452461 14.747328 0))"
#> attr(,"label")
#> [1] "polygon_wkt"

Now that we understand how robotoolbox stores spatial question types, we can convert these columns into spatial objects suitable for spatial data analysis.

Geopoint

The standard approach to manipulate spatial vector data in R involves using the sf package. sf stands for Simple Features and it extends a data.frame by adding a geometry list-column. It’s a spatially enabled data.frame. It provides an interface to the popular GDAL, GEOS, PRØJ and S2 libraries. It can be used to efficiently manipulate and visualize spatial vector data.

Creating an sf object from a text column that contains WKT characters is straightforward. The sf::st_as_sf function can be used to turn the data.frame with a WKT column into an sf object.

point_sf <- st_as_sf(data_spatial,
                     wkt = "point_wkt", crs = 4326)
mapview(point_sf)

Geotrace

We can also transform a data.frame with a column from a geotrace question to an sf object with a LINESTRING geometry. The WKT column is named line_wkt.

line_sf <- st_as_sf(data_spatial,
                     wkt = "line_wkt", crs = 4326)
mapview(line_sf)

Geoshape

The column polygon_wkt can be used to create an sf polygon object. It’s a simple closed polygon.

poly_sf <- st_as_sf(data_spatial,
                    wkt = "polygon_wkt", crs = 4326)
mapview(poly_sf)

Not only does robotoolbox rely on the sf package, but it also leverages other packages from the same ecosystem to provide robust spatial data analysis for KoboToolbox users.

You can learn a lot about the sf packages and spatial data analysis with R from the excellent Geocomputation with R book and through the extensive sf package documentation.