PSA Training Series github.com/precision-sustainable-ag

Database Querying with R — Brian W. Davis 2020-01-07

  1. What is a DB? (video)
  2. Getting started with R (video)
  3. How to use a local DB (video)
  4. How to use the PSA DB (video)

1 Getting started with R

First up, is R the only way to interact with databases? No, but it’s a scripting language and development environment specifically designed for ingesting, analyzing, and communicating data. You can achieve all the tasks in this series using Python, SAS, JavaScript, etc.

1.1 What are these documents?

1.1.1 Non-interactive HTML

In this series, there are two files for each step in the tutorial. One is called ###_Title.nb.html, and it’s a plain HTML file you can open in your browser. In that file, you will see plain text, as well as boxes of code. The grey boxes have code you can copy-paste into an R script, or line-by-line at the R console. The white boxes below show the output you should see after running each chunk. They look like this:

[1] -0.001956077

1.1.2 Interactive R Notebooks

There are also files called ###_Title.Rmd. These are special R scripts you can open in RStudio (see below). The text you’re reading now is in there, but the code chunks will look like this:

Within RStudio:
‍```{r}                     
mean(rnorm(1000))
‍```

If you click the “Run Current Chunk” button (in RStudio, not in the HTML document), that section of code will execute, and the R output will appear immediately below it in the document. You can play around with the code and see how the output is affected. Each chunk shares an environment with the other chunks in the document, so if you mess something up and want to run all the previous ones to reset, click the “Run All Chunks Above” button .

2 Download R

A mirror of the R core application is available at https://cran.rstudio.com/, and for Mac and Windows, setup is a breeze. Linux has a few challenges, usually revolving around installing packages from their source code instead of distributed binaries, so if you’re a Linux user, you probably have more expertise than I do on the topic.

2.1 Optionally RStudio

I strongly recommend using RStudio, available from https://rstudio.com/products/rstudio/download/#download. It’s an integrated development environment, or IDE, so you can see your code and output together. It also has lots of features for productivity, like autocomplete and syntax highlighting.

3 Installing packages

Base R is useful, but for this project we are going to take advantage of a few database-specific packages. Pay attention after you run each of these lines! When you run install.packages, lots of informative messages and download progress bars are printed, but there may be errors and warnings as well.

3.1 Download DBI

This package provides a backend for database drivers to communicate with R in a uniform way.

3.2 Download RPostgres

This package contains the driver to connect to PostgreSQL databases, like the PSA On-Farm DB.

WARNING: Due to a bug in the newest release of this package (1.2.0, as of late December 2019), connections to the database will fail. Instead, you need versions 1.1.3 or earlier. I’ve tested connections on Windows, MacOS, and Linux with 1.1.1, so that’s the instruction I’m giving here. I hope this will be resolved soon, and you will be able use the regular installation procedure to get the latest package.

3.3 Download RSQLite

This package contains both the driver and the database system itself for SQLite3. It’s a lightweight DB that you can run on your computer for testing and learning (in the next tutorial).

3.4 Optionally download dplyr and dbplyr

While not strictly required, I will be using the {dbplyr} interface to translate R code to the SQL backend. The syntax is much more user-friendly and intuitive, and it’s useful for your local analyses as well. There are many tutorials online for learning {dplyr}, so this will only be a crash course in what’s necessary.

A good resource for databases and R in general is https://db.rstudio.com/, which has sections for different database systems, how SQL translation works, etc.

3.4.1 Even more optionally

There are some packages I use that you do not need for the basic outline of the tutorial. They’re mostly for demonstrating plots, or when I want to show you an illustrative code chunk. However, these are not required to just query the database. Of course, I obviously find them useful in other analyses beyond this tutorial. If you do want to run every single line of code that I do as you follow along though, here’s what you’ll see used:

3.4.1.1 Visualization:

3.4.1.2 Functional loops and string/datetime manipulation

4 What on earth is that funny looking %>%

In a lot of new R code, especially so-called {tidyverse}-flavored code, you’ll see something called a pipe operator, %>%. It’s for function composition, and you can think of it like reading your code out loud, and saying “then” every time you see it.

[1] 0.5775481 0.9663637 1.2255812 1.2698123 1.5540718

This is identical to sqrt(abs(sort(rnorm(5)))). Whether you prefer the nested-parentheses style or the pipe-then style is up to you, just be aware that I’ll be using the pipes in some of these tutorials.

The pipe is especially useful for the table verbs of {dplyr}, which usually take a dataframe as their first argument, and return a dataframe as output. This way they can be chained together. Here’s an example of that:

# A tibble: 2 x 2
  Species        m
  <fct>      <dbl>
1 versicolor  5.72
2 virginica  11.3 

This code says:

  • Use the built-in iris dataset
  • Keep only the rows where iris$Species is not “setosa”
  • Keep only the columns for petal length/width and species
  • Make a new column (Petal.Area) and add it to the right of the dataframe, multiplying petal length and width
  • Separate the rows into groups based on what’s in the species column
  • Summarize all the rows in each group to a single row, with an observation m that’s the mean of our new Petal.Area

If you’re following along with this code, I recommend running each chunk of lines up to the %>% to see how each step works, like this:

LS0tCnRpdGxlOiAiMDAyIC0gR2V0dGluZyBzdGFydGVkIHdpdGggUiIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6IAogICAgaGlnaGxpZ2h0OiB0YW5nbwogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMKICAgIHRoZW1lOiByZWFkYWJsZQogICAgdG9jOiB5ZXMKICAgIHRvY19mbG9hdDogeWVzCiAgICBjb2RlX2ZvbGRpbmc6IG5vbmUKICAgIGluY2x1ZGVzOgogICAgICBiZWZvcmVfYm9keTogYXNzZXRzL2hlYWRlci5odG1sCiAgICAgIGFmdGVyX2JvZHk6IGFzc2V0cy9mb290ZXIuaHRtbAotLS0KCiMgR2V0dGluZyBzdGFydGVkIHdpdGggUgoKRmlyc3QgdXAsIGlzIFIgdGhlIG9ubHkgd2F5IHRvIGludGVyYWN0IHdpdGggZGF0YWJhc2VzPyBObywgYnV0IGl0J3MgYSBzY3JpcHRpbmcgbGFuZ3VhZ2UgYW5kIGRldmVsb3BtZW50IGVudmlyb25tZW50IHNwZWNpZmljYWxseSBkZXNpZ25lZCBmb3IgaW5nZXN0aW5nLCBhbmFseXppbmcsIGFuZCBjb21tdW5pY2F0aW5nIGRhdGEuIFlvdSBjYW4gYWNoaWV2ZSBhbGwgdGhlIHRhc2tzIGluIHRoaXMgc2VyaWVzIHVzaW5nIFB5dGhvbiwgU0FTLCBKYXZhU2NyaXB0LCBldGMuCgojIyBXaGF0IGFyZSB0aGVzZSBkb2N1bWVudHM/CgojIyMgTm9uLWludGVyYWN0aXZlIEhUTUwKCkluIHRoaXMgc2VyaWVzLCB0aGVyZSBhcmUgdHdvIGZpbGVzIGZvciBlYWNoIHN0ZXAgaW4gdGhlIHR1dG9yaWFsLiBPbmUgaXMgY2FsbGVkIGAjIyNfVGl0bGUubmIuaHRtbGAsIGFuZCBpdCdzIGEgcGxhaW4gSFRNTCBmaWxlIHlvdSBjYW4gb3BlbiBpbiB5b3VyIGJyb3dzZXIuIEluIHRoYXQgZmlsZSwgeW91IHdpbGwgc2VlIHBsYWluIHRleHQsIGFzIHdlbGwgYXMgYm94ZXMgb2YgY29kZS4gVGhlIGdyZXkgYm94ZXMgaGF2ZSBjb2RlIHlvdSBjYW4gY29weS1wYXN0ZSBpbnRvIGFuIFIgc2NyaXB0LCBvciBsaW5lLWJ5LWxpbmUgYXQgdGhlIFIgY29uc29sZS4gVGhlIHdoaXRlIGJveGVzIGJlbG93IHNob3cgdGhlIG91dHB1dCB5b3Ugc2hvdWxkIHNlZSBhZnRlciBydW5uaW5nIGVhY2ggY2h1bmsuIFRoZXkgbG9vayBsaWtlIHRoaXM6CgpgYGB7cn0KbWVhbihybm9ybSgxMDAwKSkKYGBgCgojIyMgSW50ZXJhY3RpdmUgUiBOb3RlYm9va3MKVGhlcmUgYXJlIGFsc28gZmlsZXMgY2FsbGVkIGAjIyNfVGl0bGUuUm1kYC4gVGhlc2UgYXJlIHNwZWNpYWwgUiBzY3JpcHRzIHlvdSBjYW4gb3BlbiBpbiBSU3R1ZGlvIChzZWUgYmVsb3cpLiBUaGUgdGV4dCB5b3UncmUgcmVhZGluZyBub3cgaXMgaW4gdGhlcmUsIGJ1dCB0aGUgY29kZSBjaHVua3Mgd2lsbCBsb29rIGxpa2UgdGhpczoKCj4gKipXaXRoaW4gUlN0dWRpbzoqKgo+IDxwcmU+Jnp3ajtgYGB7cn0gICAgICAgICAgICAgICAgIDxpbWcgc3JjPSJhc3NldHMvY29nLXNvbGlkLnN2ZyIgc3R5bGU9ImhlaWdodDogMWVtOyI+Jm5ic3A7Jm5ic3A7PGltZyBzcmM9ImFzc2V0cy9jYXJldC1zcXVhcmUtZG93bi1yZWd1bGFyLnN2ZyIgc3R5bGU9ImhlaWdodDogMWVtOyI+Jm5ic3A7Jm5ic3A7PGltZyBzcmM9ImFzc2V0cy9wbGF5LXNvbGlkLnN2ZyIgc3R5bGU9ImhlaWdodDogMWVtOyI+Cm1lYW4ocm5vcm0oMTAwMCkpCiZ6d2o7YGBgPC9wcmU+Cj4gCj4gSWYgeW91IGNsaWNrIHRoZSAiUnVuIEN1cnJlbnQgQ2h1bmsiIGJ1dHRvbiA8aW1nIHNyYz0iYXNzZXRzL3BsYXktc29saWQuc3ZnIiBzdHlsZT0iaGVpZ2h0OiAxZW07Ij4gKGluIFJTdHVkaW8sIG5vdCBpbiB0aGUgSFRNTCBkb2N1bWVudCksIHRoYXQgc2VjdGlvbiBvZiBjb2RlIHdpbGwgZXhlY3V0ZSwgYW5kIHRoZSBSIG91dHB1dCB3aWxsIGFwcGVhciBpbW1lZGlhdGVseSBiZWxvdyBpdCBpbiB0aGUgZG9jdW1lbnQuIFlvdSBjYW4gcGxheSBhcm91bmQgd2l0aCB0aGUgY29kZSBhbmQgc2VlIGhvdyB0aGUgb3V0cHV0IGlzIGFmZmVjdGVkLiBFYWNoIGNodW5rIHNoYXJlcyBhbiBlbnZpcm9ubWVudCB3aXRoIHRoZSBvdGhlciBjaHVua3MgaW4gdGhlIGRvY3VtZW50LCBzbyBpZiB5b3UgbWVzcyBzb21ldGhpbmcgdXAgYW5kIHdhbnQgdG8gcnVuIGFsbCB0aGUgcHJldmlvdXMgb25lcyB0byByZXNldCwgY2xpY2sgdGhlICJSdW4gQWxsIENodW5rcyBBYm92ZSIgYnV0dG9uIDxpbWcgc3JjPSJhc3NldHMvY2FyZXQtc3F1YXJlLWRvd24tcmVndWxhci5zdmciIHN0eWxlPSJoZWlnaHQ6IDFlbTsiPi4KCiMgRG93bmxvYWQgUgoKQSBtaXJyb3Igb2YgdGhlIFIgY29yZSBhcHBsaWNhdGlvbiBpcyBhdmFpbGFibGUgYXQgW2h0dHBzOi8vY3Jhbi5yc3R1ZGlvLmNvbS9dKGh0dHBzOi8vY3Jhbi5yc3R1ZGlvLmNvbS8pe3RhcmdldD0iX2JsYW5rIn0sIGFuZCBmb3IgTWFjIGFuZCBXaW5kb3dzLCBzZXR1cCBpcyBhIGJyZWV6ZS4gTGludXggaGFzIGEgZmV3IGNoYWxsZW5nZXMsIHVzdWFsbHkgcmV2b2x2aW5nIGFyb3VuZCBpbnN0YWxsaW5nIHBhY2thZ2VzIGZyb20gdGhlaXIgc291cmNlIGNvZGUgaW5zdGVhZCBvZiBkaXN0cmlidXRlZCBiaW5hcmllcywgc28gaWYgeW91J3JlIGEgTGludXggdXNlciwgeW91IHByb2JhYmx5IGhhdmUgbW9yZSBleHBlcnRpc2UgdGhhbiBJIGRvIG9uIHRoZSB0b3BpYy4KCiMjIE9wdGlvbmFsbHkgUlN0dWRpbwoKSSBzdHJvbmdseSByZWNvbW1lbmQgdXNpbmcgUlN0dWRpbywgYXZhaWxhYmxlIGZyb20gW2h0dHBzOi8vcnN0dWRpby5jb20vcHJvZHVjdHMvcnN0dWRpby9kb3dubG9hZC8jZG93bmxvYWRdKGh0dHBzOi8vcnN0dWRpby5jb20vcHJvZHVjdHMvcnN0dWRpby9kb3dubG9hZC8jZG93bmxvYWQpe3RhcmdldD0iX2JsYW5rIn0uIEl0J3MgYW4gaW50ZWdyYXRlZCBkZXZlbG9wbWVudCBlbnZpcm9ubWVudCwgb3IgSURFLCBzbyB5b3UgY2FuIHNlZSB5b3VyIGNvZGUgYW5kIG91dHB1dCB0b2dldGhlci4gSXQgYWxzbyBoYXMgbG90cyBvZiBmZWF0dXJlcyBmb3IgcHJvZHVjdGl2aXR5LCBsaWtlIGF1dG9jb21wbGV0ZSBhbmQgc3ludGF4IGhpZ2hsaWdodGluZy4KCiMgSW5zdGFsbGluZyBwYWNrYWdlcwoKQmFzZSBSIGlzIHVzZWZ1bCwgYnV0IGZvciB0aGlzIHByb2plY3Qgd2UgYXJlIGdvaW5nIHRvIHRha2UgYWR2YW50YWdlIG9mIGEgZmV3IGRhdGFiYXNlLXNwZWNpZmljIHBhY2thZ2VzLiBQYXkgYXR0ZW50aW9uIGFmdGVyIHlvdSBydW4gZWFjaCBvZiB0aGVzZSBsaW5lcyEgV2hlbiB5b3UgcnVuICoqYGluc3RhbGwucGFja2FnZXNgKiosIGxvdHMgb2YgaW5mb3JtYXRpdmUgbWVzc2FnZXMgYW5kIGRvd25sb2FkIHByb2dyZXNzIGJhcnMgYXJlIHByaW50ZWQsIGJ1dCB0aGVyZSBtYXkgYmUgZXJyb3JzIGFuZCB3YXJuaW5ncyBhcyB3ZWxsLgoKIyMgRG93bmxvYWQgREJJCgpUaGlzIHBhY2thZ2UgcHJvdmlkZXMgYSBiYWNrZW5kIGZvciBkYXRhYmFzZSBkcml2ZXJzIHRvIGNvbW11bmljYXRlIHdpdGggUiBpbiBhIHVuaWZvcm0gd2F5LgoKYGBge3IgZXZhbCA9IEZBTFNFfQppbnN0YWxsLnBhY2thZ2VzKCJEQkkiKQpgYGAKCiMjIERvd25sb2FkIFJQb3N0Z3JlcwoKVGhpcyBwYWNrYWdlIGNvbnRhaW5zIHRoZSBkcml2ZXIgdG8gY29ubmVjdCB0byBQb3N0Z3JlU1FMIGRhdGFiYXNlcywgbGlrZSB0aGUgUFNBIE9uLUZhcm0gREIuCgo+ICoqV0FSTklORzoqKiBEdWUgdG8gYSBidWcgaW4gdGhlIG5ld2VzdCByZWxlYXNlIG9mIHRoaXMgcGFja2FnZSAoKipgMS4yLjBgKiosIGFzIG9mIGxhdGUgRGVjZW1iZXIgMjAxOSksIGNvbm5lY3Rpb25zIHRvIHRoZSBkYXRhYmFzZSB3aWxsIGZhaWwuIEluc3RlYWQsIHlvdSBuZWVkIHZlcnNpb25zICoqYDEuMS4zYCoqIG9yIGVhcmxpZXIuIEkndmUgdGVzdGVkIGNvbm5lY3Rpb25zIG9uIFdpbmRvd3MsIE1hY09TLCBhbmQgTGludXggd2l0aCAqKmAxLjEuMWAqKiwgc28gdGhhdCdzIHRoZSBpbnN0cnVjdGlvbiBJJ20gZ2l2aW5nIGhlcmUuIEkgaG9wZSB0aGlzIHdpbGwgYmUgcmVzb2x2ZWQgc29vbiwgYW5kIHlvdSB3aWxsIGJlIGFibGUgdXNlIHRoZSByZWd1bGFyIGluc3RhbGxhdGlvbiBwcm9jZWR1cmUgdG8gZ2V0IHRoZSBsYXRlc3QgcGFja2FnZS4KCmBgYHtyIGV2YWwgPSBGQUxTRX0KIyBpbnN0YWxsLnBhY2thZ2VzKCJSUG9zdGdyZXMiKQoKaW5zdGFsbC5wYWNrYWdlcygiZGV2dG9vbHMiKQpkZXZ0b29sczo6aW5zdGFsbF92ZXJzaW9uKAogICJSUG9zdGdyZXMiLCAKICB2ZXJzaW9uID0gIjEuMS4xIiwgCiAgcmVwb3MgPSAiaHR0cDovL2NyYW4udXMuci1wcm9qZWN0Lm9yZyIKICApCmBgYAoKIyMgRG93bmxvYWQgUlNRTGl0ZQoKVGhpcyBwYWNrYWdlIGNvbnRhaW5zIGJvdGggdGhlIGRyaXZlciBhbmQgdGhlIGRhdGFiYXNlIHN5c3RlbSBpdHNlbGYgZm9yIFNRTGl0ZTMuIEl0J3MgYSBsaWdodHdlaWdodCBEQiB0aGF0IHlvdSBjYW4gcnVuIG9uIHlvdXIgY29tcHV0ZXIgZm9yIHRlc3RpbmcgYW5kIGxlYXJuaW5nIChpbiB0aGUgbmV4dCB0dXRvcmlhbCkuCgpgYGB7ciBldmFsID0gRkFMU0V9Cmluc3RhbGwucGFja2FnZXMoIlJTUUxpdGUiKQpgYGAKCiMjIE9wdGlvbmFsbHkgZG93bmxvYWQgZHBseXIgYW5kIGRicGx5cgoKV2hpbGUgbm90IHN0cmljdGx5IHJlcXVpcmVkLCBJIHdpbGwgYmUgdXNpbmcgdGhlIGB7ZGJwbHlyfWAgaW50ZXJmYWNlIHRvIHRyYW5zbGF0ZSBSIGNvZGUgdG8gdGhlIFNRTCBiYWNrZW5kLiBUaGUgc3ludGF4IGlzIG11Y2ggbW9yZSB1c2VyLWZyaWVuZGx5IGFuZCBpbnR1aXRpdmUsIGFuZCBpdCdzIHVzZWZ1bCBmb3IgeW91ciBsb2NhbCBhbmFseXNlcyBhcyB3ZWxsLiBUaGVyZSBhcmUgbWFueSB0dXRvcmlhbHMgb25saW5lIGZvciBsZWFybmluZyBge2RwbHlyfWAsIHNvIHRoaXMgd2lsbCBvbmx5IGJlIGEgY3Jhc2ggY291cnNlIGluIHdoYXQncyBuZWNlc3NhcnkuCgpBIGdvb2QgcmVzb3VyY2UgZm9yIGRhdGFiYXNlcyBhbmQgUiBpbiBnZW5lcmFsIGlzIFtodHRwczovL2RiLnJzdHVkaW8uY29tL10oaHR0cHM6Ly9kYi5yc3R1ZGlvLmNvbS8pe3RhcmdldD0iX2JsYW5rIn0sIHdoaWNoIGhhcyBzZWN0aW9ucyBmb3IgZGlmZmVyZW50IGRhdGFiYXNlIHN5c3RlbXMsIGhvdyBTUUwgdHJhbnNsYXRpb24gd29ya3MsIGV0Yy4KCmBgYHtyIGV2YWwgPSBGQUxTRX0KaW5zdGFsbC5wYWNrYWdlcygiZHBseXIiKQppbnN0YWxsLnBhY2thZ2VzKCJkYnBseXIiKQpgYGAKCiMjIyBFdmVuIG1vcmUgb3B0aW9uYWxseQoKVGhlcmUgYXJlIHNvbWUgcGFja2FnZXMgSSB1c2UgdGhhdCB5b3UgZG8gbm90ICoqbmVlZCoqIGZvciB0aGUgYmFzaWMgb3V0bGluZSBvZiB0aGUgdHV0b3JpYWwuIFRoZXkncmUgbW9zdGx5IGZvciBkZW1vbnN0cmF0aW5nIHBsb3RzLCBvciB3aGVuIEkgd2FudCB0byBzaG93IHlvdSBhbiBpbGx1c3RyYXRpdmUgY29kZSBjaHVuay4gSG93ZXZlciwgdGhlc2UgYXJlIG5vdCByZXF1aXJlZCB0byBqdXN0IHF1ZXJ5IHRoZSBkYXRhYmFzZS4gT2YgY291cnNlLCBJIG9idmlvdXNseSBmaW5kIHRoZW0gdXNlZnVsIGluIG90aGVyIGFuYWx5c2VzIGJleW9uZCB0aGlzIHR1dG9yaWFsLiBJZiB5b3UgZG8gd2FudCB0byBydW4gZXZlcnkgc2luZ2xlIGxpbmUgb2YgY29kZSB0aGF0IEkgZG8gYXMgeW91IGZvbGxvdyBhbG9uZyB0aG91Z2gsIGhlcmUncyB3aGF0IHlvdSdsbCBzZWUgdXNlZDoKCiMjIyMgVmlzdWFsaXphdGlvbjoKCmBgYHtyIGV2YWwgPSBGQUxTRX0KaW5zdGFsbC5wYWNrYWdlcygiZ2dwbG90MiIpCmBgYAoKIyMjIyBGdW5jdGlvbmFsIGxvb3BzIGFuZCBzdHJpbmcvZGF0ZXRpbWUgbWFuaXB1bGF0aW9uCgpgYGB7ciBldmFsID0gRkFMU0V9Cmluc3RhbGwucGFja2FnZXMoInB1cnJyIikKaW5zdGFsbC5wYWNrYWdlcygic3RyaW5nciIpCmluc3RhbGwucGFja2FnZXMoImx1YnJpZGF0ZSIpCmBgYAoKIyMjIyBNYXBwaW5nCgpgYGB7ciBldmFsID0gRkFMU0V9Cmluc3RhbGwucGFja2FnZXMoInNmIikKaW5zdGFsbC5wYWNrYWdlcygicm5hdHVyYWxlYXJ0aGRhdGEiKQppbnN0YWxsLnBhY2thZ2VzKCJsZWFmbGV0IikKYGBgCgojIFdoYXQgb24gZWFydGggaXMgdGhhdCBmdW5ueSBsb29raW5nICoqYCU+JWAqKgoKSW4gYSBsb3Qgb2YgbmV3IFIgY29kZSwgZXNwZWNpYWxseSBzby1jYWxsZWQgYHt0aWR5dmVyc2V9YC1mbGF2b3JlZCBjb2RlLCB5b3UnbGwgc2VlIHNvbWV0aGluZyBjYWxsZWQgYSAqcGlwZSBvcGVyYXRvciosICoqYCU+JWAqKi4gSXQncyBmb3IgZnVuY3Rpb24gY29tcG9zaXRpb24sIGFuZCB5b3UgY2FuIHRoaW5rIG9mIGl0IGxpa2UgcmVhZGluZyB5b3VyIGNvZGUgb3V0IGxvdWQsIGFuZCBzYXlpbmcgInRoZW4iIGV2ZXJ5IHRpbWUgeW91IHNlZSBpdC4KCmBgYHtyfQpsaWJyYXJ5KGRwbHlyLCB3YXJuLmNvbmZsaWN0cyA9IEZBTFNFKQoKcm5vcm0oNSkgJT4lICAgIyBnZW5lcmF0ZSA1IHJhbmRvbSBudW1iZXJzCiAgc29ydCgpICU+JSAgICAjIFRIRU4gc29ydCB0aG9zZQogIGFicygpICU+JSAgICAgIyBUSEVOIHRha2UgdGhlIGFic29sdXRlIHZhbHVlIG9mIHRob3NlCiAgc3FydCgpICAgICAgICAjIFRIRU4gdGFrZSB0aGUgc3F1YXJlLXJvb3Qgb2YgdGhvc2UKYGBgCgpUaGlzIGlzIGlkZW50aWNhbCB0byAqKmBzcXJ0KGFicyhzb3J0KHJub3JtKDUpKSkpYCoqLiBXaGV0aGVyIHlvdSBwcmVmZXIgdGhlIG5lc3RlZC1wYXJlbnRoZXNlcyBzdHlsZSBvciB0aGUgcGlwZS10aGVuIHN0eWxlIGlzIHVwIHRvIHlvdSwganVzdCBiZSBhd2FyZSB0aGF0IEknbGwgYmUgdXNpbmcgdGhlIHBpcGVzIGluIHNvbWUgb2YgdGhlc2UgdHV0b3JpYWxzLgoKVGhlIHBpcGUgaXMgZXNwZWNpYWxseSB1c2VmdWwgZm9yIHRoZSAqKnRhYmxlIHZlcmJzKiogb2YgYHtkcGx5cn1gLCB3aGljaCB1c3VhbGx5IHRha2UgYSBkYXRhZnJhbWUgYXMgdGhlaXIgZmlyc3QgYXJndW1lbnQsIGFuZCByZXR1cm4gYSBkYXRhZnJhbWUgYXMgb3V0cHV0LiBUaGlzIHdheSB0aGV5IGNhbiBiZSBjaGFpbmVkIHRvZ2V0aGVyLiBIZXJlJ3MgYW4gZXhhbXBsZSBvZiB0aGF0OgoKYGBge3IgcGFnZWQucHJpbnQgPSBGQUxTRX0KaXJpcyAlPiUgCiAgZmlsdGVyKFNwZWNpZXMgIT0gInNldG9zYSIpICU+JSAKICBzZWxlY3QoUGV0YWwuTGVuZ3RoLCBQZXRhbC5XaWR0aCwgU3BlY2llcykgJT4lIAogIG11dGF0ZShQZXRhbC5BcmVhID0gUGV0YWwuTGVuZ3RoICogUGV0YWwuV2lkdGgpICU+JSAKICBncm91cF9ieShTcGVjaWVzKSAlPiUgCiAgc3VtbWFyaXplKG0gPSBtZWFuKFBldGFsLkFyZWEpKQpgYGAKClRoaXMgY29kZSBzYXlzOgoKKiBVc2UgdGhlIGJ1aWx0LWluIGBpcmlzYCBkYXRhc2V0CiogS2VlcCBvbmx5IHRoZSAqKnJvd3MqKiB3aGVyZSBgaXJpcyRTcGVjaWVzYCBpcyBub3QgInNldG9zYSIKKiBLZWVwIG9ubHkgdGhlICoqY29sdW1ucyoqIGZvciBwZXRhbCBsZW5ndGgvd2lkdGggYW5kIHNwZWNpZXMKKiBNYWtlIGEgbmV3IGNvbHVtbiAoYFBldGFsLkFyZWFgKSBhbmQgYWRkIGl0IHRvIHRoZSByaWdodCBvZiB0aGUgZGF0YWZyYW1lLCBtdWx0aXBseWluZyBwZXRhbCBsZW5ndGggYW5kIHdpZHRoCiogU2VwYXJhdGUgdGhlIHJvd3MgaW50byBncm91cHMgYmFzZWQgb24gd2hhdCdzIGluIHRoZSBzcGVjaWVzIGNvbHVtbgoqIFN1bW1hcml6ZSBhbGwgdGhlIHJvd3MgaW4gZWFjaCBncm91cCB0byBhIHNpbmdsZSByb3csIHdpdGggYW4gb2JzZXJ2YXRpb24gYG1gIHRoYXQncyB0aGUgbWVhbiBvZiBvdXIgbmV3IGBQZXRhbC5BcmVhYAoKSWYgeW91J3JlIGZvbGxvd2luZyBhbG9uZyB3aXRoIHRoaXMgY29kZSwgSSByZWNvbW1lbmQgcnVubmluZyBlYWNoIGNodW5rIG9mIGxpbmVzIHVwIHRvIHRoZSBgJT4lYCB0byBzZWUgaG93IGVhY2ggc3RlcCB3b3JrcywgbGlrZSB0aGlzOgoKYGBge3IgZXZhbCA9IEZBTFNFLCBwYWdlZC5wcmludCA9IEZBTFNFfQppcmlzCgppcmlzICU+JSAKICBmaWx0ZXIoU3BlY2llcyAhPSAic2V0b3NhIikgCgppcmlzICU+JSAKICBmaWx0ZXIoU3BlY2llcyAhPSAic2V0b3NhIikgJT4lIAogIHNlbGVjdChQZXRhbC5MZW5ndGgsIFBldGFsLldpZHRoLCBTcGVjaWVzKSAKCmlyaXMgJT4lIAogIGZpbHRlcihTcGVjaWVzICE9ICJzZXRvc2EiKSAlPiUgCiAgc2VsZWN0KFBldGFsLkxlbmd0aCwgUGV0YWwuV2lkdGgsIFNwZWNpZXMpICU+JSAKICBtdXRhdGUoUGV0YWwuQXJlYSA9IFBldGFsLkxlbmd0aCAqIFBldGFsLldpZHRoKSAKCmlyaXMgJT4lIAogIGZpbHRlcihTcGVjaWVzICE9ICJzZXRvc2EiKSAlPiUgCiAgc2VsZWN0KFBldGFsLkxlbmd0aCwgUGV0YWwuV2lkdGgsIFNwZWNpZXMpICU+JSAKICBtdXRhdGUoUGV0YWwuQXJlYSA9IFBldGFsLkxlbmd0aCAqIFBldGFsLldpZHRoKSAlPiUgCiAgZ3JvdXBfYnkoU3BlY2llcykgCgppcmlzICU+JSAKICBmaWx0ZXIoU3BlY2llcyAhPSAic2V0b3NhIikgJT4lIAogIHNlbGVjdChQZXRhbC5MZW5ndGgsIFBldGFsLldpZHRoLCBTcGVjaWVzKSAlPiUgCiAgbXV0YXRlKFBldGFsLkFyZWEgPSBQZXRhbC5MZW5ndGggKiBQZXRhbC5XaWR0aCkgJT4lIAogIGdyb3VwX2J5KFNwZWNpZXMpICU+JSAKICBzdW1tYXJpemUobSA9IG1lYW4oUGV0YWwuQXJlYSkpCmBgYAo=

precisionsustainableag.org


Icons: fontawesome.com, BY 4.0 | This work, BY-SA 4.0