├── .gitignore ├── LICENSE ├── README.md ├── Shiny-leaflet-tutorial.Rmd ├── ShinyLeaflet-tutorial.Rproj ├── code_of_conduct.md ├── data └── pollen_data.csv └── images └── finalMap.png /.gitignore: -------------------------------------------------------------------------------- 1 | # History files 2 | .Rhistory 3 | .Rapp.history 4 | 5 | # Session Data files 6 | .RData 7 | 8 | # Example code in package build process 9 | *-Ex.R 10 | 11 | # RStudio files 12 | .Rproj.user/ 13 | 14 | # produced vignettes 15 | vignettes/*.html 16 | vignettes/*.pdf 17 | 18 | # OAuth2 token, see https://github.com/hadley/httr/releases/tag/v0.3 19 | .httr-oauth 20 | .Rproj.user 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Simon 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Tutorial - Using Shiny & Leaflet to Explore Spatial Datasets 2 | 3 | By: [Simon Goring](http://github.com/SimonGoring) 4 | Date: March 7, 2016 5 | 6 | A tutorial to test out some ideas for a Shiny/Leaflet interaction. This tutorial will be presented as part of the UBC Mozilla [R Study Group] (https://github.com/minisciencegirl/studyGroup). 7 | 8 | The intent is to help you get started using both [leaflet](https://rstudio.github.io/leaflet/) and [Shiny](http://shiny.rstudio.com/) together in R to do basic data exploration with geospatial data. The tutorial assumes you have some experience in R, but takes a "plug & play" approach - copy the code as is, and then play around with it. Even a beginner should be able to get this code to work. 9 | 10 | In this tutorial you will: 11 | 12 | 1. Learn briefly about leaflet & shiny 13 | 2. Install the leaflet and Shiny packages 14 | 3. Produce a very basic leaflet map and learn some elementary functions 15 | 4. Download a file from GitHub 16 | 5. Build a simply Shiny app with a slider bar and drop down menu 17 | 6. Explore a dataset. 18 | 19 | I've tried to structure the main document to be a 'chatty' tutorial, so you can walk through things on your own, but ultimately we only get so far in developing the tutorial because the workshop session is only one hour long. 20 | 21 | Using RStudio you can fork (or clone) the repository locally and then "run" it using rmarkdown. If you do that you will have an html document wth embedded Shiny'Leaflet applets. It's pretty cool. It does run from the web, but my current hosting situation isn't great. 22 | 23 | At the end, you'll make a nice little map like the one below, of data from the [Neotoma Paleoecological Database](http://neotomadb.org), but the lesson is broadly applicable. I just know this data best. 24 | 25 | ![leaflet_map](images/finalMap.png) 26 | 27 | ## Contribution 28 | 29 | You are welcome to fork & contribute to this repository, but contributors are expected to follow the [Code of Conduct](http://github.com/SimonGoring/ShinyLeaflet-tutorial/code_of_conduct.md) posted in this repository. 30 | -------------------------------------------------------------------------------- /Shiny-leaflet-tutorial.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Spatial Data On the Web" 3 | author: "Simon Goring - Dash Consultants" 4 | date: "March 4, 2016" 5 | 6 | runtime: shiny 7 | output: 8 | html_document: 9 | theme: journal 10 | toc: true 11 | toc_depth: 2 12 | number_sections: true 13 | code_folding: show 14 | 15 | --- 16 | 17 | # An Introduction to Leaflet and Shiny in R: 18 | 19 | This tutorial will help you get started using both leaflet and shiny in R to do basic data exploration with geospatial data. 20 | In this tutorial you will: 21 | 22 | 1. Learn briefly about leaflet & shiny 23 | 2. Install the leaflet and Shiny packages 24 | 3. Produce a very basic leaflet map and learn some elementary functions 25 | 4. Download a file from GitHub 26 | 5. Build a simply Shiny app with a slider bar and drop down menu 27 | 6. Explore a dataset. 28 | 29 | I'm going to write code here using the `magrittr` pipe style. The RStudio `leaflet` tutorial uses the same styling. I'm just learning it so I want to practice, but I will provide some examples in standard form so you can follow along. 30 | 31 | # What is Leaflet? 32 | 33 | Leaflet is a JavaScript Library for mobile-friendly mapping. Leaflet is an alternative to OpenLayers, although doesn't present all the functionality, and to the closed-source Google Maps API. 34 | 35 | Leaflet is very widely used, in part because of its flexibility and because of the broad coalition of users & developers. There are a large number of base layers available for mapping, it is modular, it supports interactive mapping, multiple geospatial data formats, and it's fairly easy & intuitive to use. 36 | 37 | This workshop will focus on using the [`leaflet`](https://rstudio.github.io/leaflet/) package for R, but wrappers also exist for Python - [`folium`](https://folium.readthedocs.org/en/latest/), and leaflet is natively developed in JavaScript. Throughout this tutorial I'll use the lowercase `leaflet` to refer to the R package and the uppercase Leaflet for the JavaScript module. 38 | 39 | Leaflet provides a set of tools for easily visualizing geospatial data, and also for navigating and investigating individual records. First, a brief introduction to Leaflet. 40 | 41 | ```{r echo = FALSE, message = FALSE, warning = FALSE, results = 'asis', width = 4, height = 4} 42 | library(leaflet) 43 | map <- leaflet(width = 400, height = 200) %>% 44 | addTiles() %>% 45 | addMarkers(lng = -123.251, 46 | lat = 49.263, 47 | popup = "You are here.") 48 | 49 | map 50 | 51 | ``` 52 | 53 | ## Installing `leaflet` and `Shiny` 54 | 55 | The R [`leaflet` package](https://rstudio.github.io/leaflet/) has been developed by [Joe Cheng](https://github.com/jcheng5) with RStudio. The package itself lives on CRAN and GitHub, so getting it is fairly straightforward: 56 | 57 | ```{r, eval=FALSE} 58 | 59 | install.packages("leaflet") 60 | 61 | # or # 62 | 63 | devtools::install_github("rstudio/leaflet") 64 | 65 | ``` 66 | 67 | Since we're going to be going a bit further with our tutorial (at the end), let's also install shiny. 68 | 69 | ```{r, eval=FALSE} 70 | 71 | install.packages("shiny") 72 | 73 | # or # 74 | 75 | devtools::install_github("rstudio/shiny") 76 | 77 | ``` 78 | 79 | Fantastic. It was pretty easy to get started. Now all you need to do is write all the code. Freaking out? Don't worry, the next section of this Tutorial will lead you through the next steps. At the end you'll say to yourself "Self, you're amazing, look at all you accomplished at the end of this tutorial!", you'll look off into the distance, and then get on with your, now bigger, now more fulfilling, life. 80 | 81 | # A Basic Leaflet Map 82 | ## Some Terminology 83 | 84 | Leaflet runs on widgets. The Widget is the thing you interact with. When we think of a fully developed leaflet object in R or any other platform, like the one above, we are thinking of a container that is filled with things. A widget is a box, and it is a box that can contain: 85 | 86 | 1. Navigation controls & decorations 87 | 2. Underlying map tiles (a street map or topographic map) 88 | 3. Popups or markers 89 | 4. Geometric shapes (circles, lines, rectangles, polygons) 90 | 91 | A `leaflet` widget is built piece by piece. We start by creating the widget, the box for all the other content we want to fill in. Once the box is made we can add pieces to it. We might want a box with a fixed street map, or without any underlying base layer. We might want all of our map points to generate popups, or we might only want to add polygons representing protected areas. Maybe we want to show networks of relatedness for genes, or degrees of similarity between the flavors served at ice cream parlors. 92 | 93 | Regardless, in all cases we need to initialize our widget. We do that with `leaflet()`. `leaflet()` accepts a number of parameters, `width`, `height` and `padding` are parameters you can use to change the appearances of your leaflet object (all in pixels). You can also pass in data directly to the leaflet map using the `data` parameter. In practice I tend not to do this, prefering to pass in data directly using the set of `add*()` functions. 94 | 95 | ```{r} 96 | leaflet(width = 400, height = 200) 97 | ``` 98 | 99 | ## Making a Map 100 | 101 | So, we start with an empty widget. If we want to do more with our widget, or make it more interactive later, it makes sense to assign it to a variable, and then add to it. We need to explicitly call the variable to make the map appear. We can add a baselayer with the `addTiles()` function, we'll see a bit more about it later, and we can make sure that the initial view is reasonable. Using `setView` we can center the map using the `lat`/`lng` parameters and the `zoom`. There are a set of `options` that you could add, defined in the `Leaflet` [documentation](http://leafletjs.com/reference.html#map-zoompanoptions) (as opposed to the `leaflet` documentation) 102 | 103 | ```{r mapWithTiles} 104 | map <- leaflet(width = 400, height = 400) 105 | map <- addTiles(map) 106 | map <- setView(map, lng = -123.251, 107 | lat = 49.263, 108 | zoom = 6) 109 | 110 | ``` 111 | 112 | Tiles are the baselayers for most web-mapping applications. They're literally `png` tiles, at various zoom levels for a grid of latitude and longitude coordinates. There are an enormous number of publically available tile layers for you to use. You can check out [Leaflet Providers](https://leaflet-extras.github.io/leaflet-providers/preview/) for a pretty exhaustive list. For one of our webmapping exercises I used a smaller number of options. You can play with them by copying & running the code block. If you change the index of `maptypes` you can see what some different map types look like. 113 | 114 | ```{r, eval = FALSE} 115 | 116 | maptypes <- c("MapQuestOpen.Aerial", 117 | "Stamen.TerrainBackground", 118 | "Esri.WorldImagery", 119 | "OpenStreetMap", 120 | "Stamen.Watercolor") 121 | 122 | # Change the index to see what the different tile-sets look like: 123 | # Now we're into the magrittr formatting. We're using "Provider" tiles here, 124 | # not the default (OpenStreetMap) Tiles: 125 | 126 | map <- leaflet() %>% 127 | addProviderTiles(maptypes[1]) 128 | 129 | ``` 130 | 131 | It's possible to stack tiles as well, for example, adding `OpenWeatherMap.Clouds` to the map abovewould give us a pretty map with some semblance of weather. Because we're in Vancouver we want to see the rain, and we want to see it close up. We could just look out the window, or we could `setView` to a fixed location, so that the widget knows where exactly we want to start (higher numbers for zooms mean more zoomed in): 132 | 133 | ```{r} 134 | map <- leaflet() %>% 135 | addProviderTiles("Stamen.Watercolor") %>% 136 | addProviderTiles("OpenWeatherMap.Rain") %>% 137 | setView(lng = -123.251, 138 | lat = 49.263, 139 | zoom = 6) 140 | 141 | ``` 142 | 143 | Provider tiles ultimately come from unique web providers. The speed and reliability of a tile set is dependent both on your own platform and on the platform of the provider. 144 | 145 | ## Adding Markers 146 | 147 | Once a map is made we often want to add some sort of marker or object on top of the map. We could add someting like a marker, or a line. These functions all follow the `add*()` format, including `addMarkers`, `addPopups`, `addCircleMarkers`, `addCircles` and others. 148 | 149 | Here we're going to add a Marker and a CircleMarker. Markers are pretty useful, the "points" of the `leaflet` universe. We can modify the Marker further using its `options` parameter. The `options` accept a set of different `markerOptions` that allow you to drag, click, and hover over the markers: 150 | 151 | ```{r eval = FALSE} 152 | map <- leaflet() %>% 153 | addProviderTiles("Esri.WorldImagery") %>% 154 | addMarkers(lng = -123.251, 155 | lat = 49.263, 156 | popup = "You are here.", 157 | options = markerOptions(draggable = TRUE, riseOnHover = TRUE)) %>% 158 | addCircleMarkers(lng = -123.261, 159 | lat = 49.273, 160 | popup = "You aren't here.", 161 | fillColor= "red", opacity = 1, 162 | options = markerOptions(draggable = FALSE, title = "Whoops")) %>% 163 | setView(lng = -123.251, 164 | lat = 49.263, 165 | zoom = 13) 166 | 167 | ``` 168 | 169 | Most of these options are more fully described in the `markerOptions` help, or the `markers` [documentation](http://leafletjs.com/reference.html#marker) for Leaflet. The pointy marker above can be dragged around willy-nilly but the circle can't. Try to switch the settings around here to drag the circle marker and leave the pointy marker fixed. 170 | 171 | ## Getting Some Data 172 | 173 | In February 2015 the University of Wisconsin's excellent Cartography Lab held a Cartographic Design Challenge to take paleoecological data, records of fossil pollen, and turn them into map products that could tell a story through cartographic design. As part of the Scott Farley created a large `csv` file from the [Neotoma Paleoecological Database](http://neotmadb.org). The data was hosted on the Design Challenge's [GitHub page], but we're just going to take the pollen data: 174 | 175 | ```{r load_pollen} 176 | 177 | # Note, this file is 4MB, so it might take some time to download. It comes from: 178 | # https://raw.github.com/scottsfarley93/DesignChallengeData/master/plants_combined/all_pollen_final.csv 179 | # but I've downloaded it and added it to the `data` folder: 180 | pollen_data <- read.csv("data/pollen_data.csv", stringsAsFactors = FALSE) 181 | 182 | # Everything gets loaded as a character string. 183 | str(pollen_data) 184 | 185 | ``` 186 | 187 | ### Very Basic Plotting 188 | 189 | The table is pretty big, there's 1110 unique sites with pollen and 84 pollen taxa. In paleoecological analysis we use the presence and proportion of various pollen types (e.g., *Pinus* or *Abies*) as a proxy for the plant that produces that pollen. We would assume that a sample containing high proportions of *Pinus* and *Picea* pollen would have high proportions of Pine and Spruce on the landscape, while a site with lots of Poaceae and *Quercus* pollen might represent an open oak savanna. Paleoecologists are often interested in patterns of change at broad spatial scales, so it would be interesting to see how things have changes in North America over the last 15,000 years. 190 | 191 | To do this, let's shrink the dataset down a bit: 192 | 193 | 1. For varous reasons it's worth being dubious about dates that are in "Radiocarbon years BP", so let's get rid of them. 194 | 2. Let's also get rid of any taxon that never has a proportion greater than 5%. 195 | 3. There's some columns that are extraneous. We really only need the SiteName, Latitude, Longitude, Age, Taxon & Pct. 196 | 4. Lastly, let's just look at samples between 15000 and -60 years BP. (1950 is ^14^C year zero because of atmospheric atomic bomb testing). 197 | 198 | ```{r, warning = FALSE} 199 | 200 | library(dplyr) 201 | 202 | # Get all taxa with proportions greater than 5%: 203 | good_taxa <- pollen_data %>% 204 | group_by(Taxon) %>% 205 | summarise(max = max(Pct)) %>% 206 | filter(max > 5) %>% 207 | select(Taxon) %>% unlist 208 | 209 | # Now subset the data and remove extraneous columns: 210 | pollen_subset <- dplyr::filter(pollen_data, 211 | !AgeType %in% "Radiocarbon years BP" & Taxon %in% good_taxa) %>% 212 | select(SiteName, Latitude, Longitude, Age, Taxon, Pct) %>% 213 | mutate_each(funs(as.numeric), Latitude, Longitude, Age, Pct) %>% na.omit 214 | 215 | plot(Latitude ~ Longitude, 216 | data = pollen_subset[!duplicated(pollen_subset$SiteName),]) 217 | 218 | ``` 219 | 220 | So, plotting the unique points here is helpful. We can see some patterns, at the very least, we know where points are and where they aren't. If we want to look at individual taxa, or individual time slices then we have to keep going back to the `plot` function. We can get a better handle on some other aspects of the data if we add these points to the map as markers. We have `r nrow(pollen_subset)` individual records, one for each pollen taxon at each site at each sampled time period. This is still a lot. 221 | 222 | ### Plotting Data With Leaflet 223 | 224 | If we plotted everything at once the computer would be unhappy. So we have two options. We could subset the data further using a call like `p_small <- pollen_subset %>% filter(!duplicated(SiteName))` or we could aggregate the *Markers* into spatial clusters. We're going to do both using the `clusterOptions` for the function `addMarkers`: 225 | 226 | ```{r} 227 | # If you add all the markers to the map at once your computer is going to be very unhappy :) 228 | # This just adds each unique point to the dataset. 229 | 230 | p_small <- pollen_subset %>% filter(!duplicated(SiteName)) 231 | 232 | # We're adding the popup here so I can click & see what sites I'm looking at. 233 | 234 | map <- leaflet() %>% 235 | addProviderTiles("Stamen.Watercolor") %>% 236 | addMarkers(lat = p_small$Latitude, 237 | lng = p_small$Longitude, 238 | clusterOptions = markerClusterOptions(), 239 | popup = as.character(p_small$SiteName)) 240 | 241 | map 242 | ``` 243 | 244 | Okay. This is as far as we're going to go with the basic plotting. Let's switch into Shiny to see how we can make this more interactive. 245 | 246 | ## Adding Shiny to the Mix 247 | 248 | One of the reasons this is so messy still is that we have unique Markers for each pollen taxon at each site, and at each time interval. This means that some sites have upwards of 300 markers at the same lat/long coordinates. That's not really going to show me much. I need a way to navigate interactively through the taxa and time periods. That's where Shiny comes in. 249 | 250 | ### A Basic Shiny Setup 251 | 252 | So, if we want to interactively switch between taxa or time periods, we need to add some controls. To do this we can move over to a Shiny App. At a bare bones level the structure is really straightforward. To build a Shiny app we need a user interface usually as a file called `ui.R` and code that is going to run our analysis on the server, called `server.R` usually. If we're being very concise we can wrap everything into a function called `shinyApp`. 253 | 254 | ```{r mostBasicShiny} 255 | # install.packages('shiny') 256 | # library(shiny) 257 | 258 | shinyApp(ui = fluidPage(titlePanel("So Simple"), 259 | sliderInput("slider", "Turn It Up", min = 0, max = 11, value = 5), 260 | mainPanel(textOutput("MainPanel"))), 261 | server = function(input, output){ 262 | output$MainPanel = renderText(input$slider) 263 | } 264 | ) 265 | 266 | ``` 267 | 268 | If we want shiny to accept inputs we need to define the type of inputs as part of the `ui`. In the example above we used a `sliderInput`, but you can have a `checkboxInput` (or `checkboxGroupInput`), `dateInput`, `dateRangeInput`, `fileInput` (for file uploads!), and all sorts of other inputs. You can use HTML formatting, add tool tips, go as crazy as you want. 269 | 270 | If you want to add tool tips to your inputs (which is a nice thing to do for users), you could wrap each of your `*Input` functions with: 271 | 272 | ``` 273 | tags$div(title = "This is the tool tip.", 274 | selectInput( . . . )) 275 | ``` 276 | 277 | There's also a useful package called `shinydashboard` that I've found helpful for making the apps look a bit prettier, and you can always embed a shiny app in a different webpage using an HTML `iframe`. 278 | 279 | ### A Full Shiny/Leaflet Example 280 | 281 | The code sample below can be divided into five sections: 282 | 283 | 1. First, we put the pollen data into a global variable at the header. 284 | 2. We wrap the whole Shiny App into a single function (this is for convenience and to simplify the example) 285 | 3. The UI defines a `fluidPage` as above, this time with a slider for time and a `selectInput` with the `unique` pollen taxa (using scientific genera for the most part). The last component of the UI is the `leafletOutput`, which will look for an `output`, which is a leaflet widget named `"MapPlot1"` to render. 286 | 4. The `server` section starts by rendering the leaflet widget, with the Stamen Watercolor tile set and setting it to `output$MapPlot1`. You can use whatever tileset you want here. The `observe` function is a `reactive`, but it's a special case (you can read more about `reactive` & `observe` on the [RStudio blog](http://shiny.rstudio.com/articles/reactivity-overview.html)) that returns a rendered objct, not a list of values. In this case, the rendered object is the leaflet widget `"MapPlot1"`, updated by first clearing any makers added using `addMarkers`, and then putting in new markers based on a subset of pollen data from a 500 year time band around the time defined in the `sliderInput` `"time"` and the `selectInput` choice `"taxon"`. 287 | 5. Finally, because the whole thing was rendering in a funny way I set the `height` `option` to 600 pixels so that everything would look nice. 288 | 289 | 290 | ```{r TheShinyExample, warning = FALSE} 291 | pollen_subset <- dplyr::filter(pollen_data, Taxon %in% good_taxa) %>% 292 | select(SiteName, Latitude, Longitude, Age, Taxon, Pct) %>% 293 | mutate_each(funs(as.numeric), Latitude, Longitude, Age, Pct) %>% na.omit 294 | 295 | library(leaflet) 296 | library(shiny) 297 | 298 | shinyApp( 299 | ui = fluidPage( 300 | sliderInput(inputId = "time", 301 | label = "Years Before Present:", 302 | min = -50, max = 15000, value = 0, step = 500), 303 | tags$div(title = "This input has a tool tip", 304 | selectInput(inputId = "taxon", 305 | label = "Taxon of Interest", 306 | choices = sort(unique(pollen_subset$Taxon)))), 307 | leafletOutput("MapPlot1") 308 | ), 309 | 310 | server = function(input, output) { 311 | 312 | output$MapPlot1 <- renderLeaflet({ 313 | leaflet() %>% 314 | addProviderTiles("Stamen.Watercolor") %>% 315 | setView(lng = -100, lat = 50, zoom = 2) 316 | }) 317 | 318 | observe({ 319 | 320 | age <- input$time 321 | taxon <- input$taxon 322 | 323 | sites <- pollen_subset %>% 324 | filter(findInterval(pollen_subset$Age, c(age - 250, age + 250)) == 1 & 325 | pollen_subset$Taxon %in% taxon) 326 | 327 | leafletProxy("MapPlot1") %>% clearMarkers() %>% 328 | addCircleMarkers(lng = sites$Longitude, 329 | lat = sites$Latitude, 330 | opacity = sites$Pct) 331 | }) 332 | }, 333 | options = list(height = 600) 334 | ) 335 | 336 | ``` 337 | 338 | Now you I explore my data easily. I can slide through time and see if there are sites that show up where they shouldn't, or sites I know are there that don't show up at all. I could make this even more interactive if I used `addPopups`, since the API for the Neotoma Paleoecological Database allows us to directly open the Neotoma Data Explorer from a URI, for example [http://api.neotomadb.org/v1/data/publications?datasetid=1001](). So I could generate HTML code within the popup that would bring me right to the explorer to look at the data more closely, or link the the publication DOI, or anything else I want to. 339 | 340 | As a quick pitch (for paleo folks) EarthCube's Cyber4Paleo Research Coordination Network is hosting a hackathon for the Neotoma Paleoecological Database and the Paleobiology Database in Boulder, CO. If you're interested it's worth checking out [this link](http://earthcube.org/content/apply-attend-c4p-paleodata-hackathon-june-2016). 341 | 342 | Obviously we can make some changes to the code. In general I start splitting my `server` and `ui` components up into two pieces to make them more manegable. You can customize your display more using `fluidRow`s and the `sidebarLayout`, but in some senses, data exploration may not need all the bells and whistles, as long as you can interactively manipulate the variable elements you're interested in seeing. -------------------------------------------------------------------------------- /ShinyLeaflet-tutorial.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | -------------------------------------------------------------------------------- /code_of_conduct.md: -------------------------------------------------------------------------------- 1 | # Contributor Code of Conduct 2 | 3 | As contributors and maintainers of this project, and in the interest of 4 | fostering an open and welcoming community, we pledge to respect all people who 5 | contribute through reporting issues, posting feature requests, updating 6 | documentation, submitting pull requests or patches, and other activities. 7 | 8 | We are committed to making participation in this project a harassment-free 9 | experience for everyone, regardless of level of experience, gender, gender 10 | identity and expression, sexual orientation, disability, personal appearance, 11 | body size, race, ethnicity, age, religion, or nationality. 12 | 13 | Examples of unacceptable behavior by participants include: 14 | 15 | * The use of sexualized language or imagery 16 | * Personal attacks 17 | * Trolling or insulting/derogatory comments 18 | * Public or private harassment 19 | * Publishing other's private information, such as physical or electronic 20 | addresses, without explicit permission 21 | * Other unethical or unprofessional conduct 22 | 23 | Project maintainers have the right and responsibility to remove, edit, or 24 | reject comments, commits, code, wiki edits, issues, and other contributions 25 | that are not aligned to this Code of Conduct, or to ban temporarily or 26 | permanently any contributor for other behaviors that they deem inappropriate, 27 | threatening, offensive, or harmful. 28 | 29 | By adopting this Code of Conduct, project maintainers commit themselves to 30 | fairly and consistently applying these principles to every aspect of managing 31 | this project. Project maintainers who do not follow or enforce the Code of 32 | Conduct may be permanently removed from the project team. 33 | 34 | This Code of Conduct applies both within project spaces and in public spaces 35 | when an individual is representing the project or its community. 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 38 | reported by contacting a project maintainer at [INSERT EMAIL ADDRESS]. All 39 | complaints will be reviewed and investigated and will result in a response that 40 | is deemed necessary and appropriate to the circumstances. Maintainers are 41 | obligated to maintain confidentiality with regard to the reporter of an 42 | incident. 43 | 44 | 45 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 46 | version 1.3.0, available at 47 | [http://contributor-covenant.org/version/1/3/0/][version] 48 | 49 | [homepage]: http://contributor-covenant.org 50 | [version]: http://contributor-covenant.org/version/1/3/0/ -------------------------------------------------------------------------------- /data/pollen_data.csv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonGoring/ShinyLeaflet-tutorial/c15eacc0d3ddb4e12b724c38bc8b24470d2dc13f/data/pollen_data.csv -------------------------------------------------------------------------------- /images/finalMap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonGoring/ShinyLeaflet-tutorial/c15eacc0d3ddb4e12b724c38bc8b24470d2dc13f/images/finalMap.png --------------------------------------------------------------------------------