Exploring your data

Importing your dataset in R

The idea behind rio is to simplify the process of importing data into R and exporting data from R. This process is, probably unnecessarily, extremely complex for beginning R users. Indeed, R supplies an entire manual describing the process of data import/export. Faster, simpler, packages with fewer dependencies have been created for many of the file types described in that document. rio aims to unify data I/O (importing and exporting) into two simple functions: import() and export() so that beginners (and experienced R users) never have to think twice (or even once) about the best way to read and write R data.

The core advantage of rio is that it makes assumptions that the user is probably willing to make. Specifically, rio uses the file extension of a file name to determine what kind of file it is. This is the same logic used by Windows OS, for example, in determining what application is associated with a given file type. By taking away the need to manually match a file type (which a beginner may not recognize) to a particular import or export function, rio allows almost all common data formats to be read with the same function.

By making import and export easy, it’s an obvious next step to also use R as a simple data conversion utility. Transferring data files between various proprietary formats is always a pain and often expensive. The convert function therefore combines import and export to easily convert between file formats (thus providing a FOSS replacement for programs like Stat/Transfer or Sledgehammer.

Installing the rio package in R

install.packages('rio') #install the package [only once]
library(rio) # load the library [every time you write a new script in which you want to import/export files]

Setting the working directory

#set the working directory to the directory in which you data files are located
setwd('/path/to/the/folder/containing/this/document')

Data Import

Rio allows you to import files in almost any format using one, typically single-argument, function. import() infers the file format from the file’s extension and calls the appropriate data import function for you, returning a simple data.frame. This works for any for the formats listed above.

mosq.dat <- import('data/GE-mosquito-ex.xlsx')
tick.dat <- import('data/GE-ticks-ex.xls')

Viewing your data

#Use head() to examine the top rows of your dataset
head(mosq.dat)
  id municipality                  village        destination  latitude
1 36    Lagodekhi Lagodekhi nature reserve  Tree, bush, grass 41.844352
2 36    Lagodekhi Lagodekhi nature reserve  Tree, bush, grass 41.844352
3 37    Lagodekhi Lagodekhi nature reserve tree,grass,toilets 41.842328
4 37    Lagodekhi Lagodekhi nature reserve tree,grass,toilets 41.842328
5 38    Lagodekhi Lagodekhi nature reserve  Tree, bush, grass 41.841335
6 38    Lagodekhi Lagodekhi nature reserve  Tree, bush, grass 41.841335
   longitude height      temp humidity wind      trap_set trap_collected point
1 46.2852763    580 28(32-23)       59   10 23.07.24/8:25  26.07.24/7:05   36a
2 46.2852763    580 28(32-23)       59   10 23.07.24/8:25  26.07.24/7:05   36b
3  46.284487    564 28(32-23)       59   10 23.07.24/8:55  26.07.24/7:25   37a
4  46.284487    564 28(32-23)       59   10 23.07.24/8:55  26.07.24/7:25   37b
5  46.284306    558 29(32-23)       57   10 23.07.24/9:15  26.07.24/7:40   38a
6  46.284306    558 29(32-23)       57   10 23.07.24/9:15  26.07.24/7:40   38b
  Ae.albopictus.count Ae.albopictus.sex Cx.pipiens.count Cx.pipiens.sex
1                  NA              <NA>               NA           <NA>
2                  NA              <NA>               NA           <NA>
3                  NA              <NA>               NA           <NA>
4                  NA              <NA>               NA           <NA>
5                  NA              <NA>               NA           <NA>
6                  NA              <NA>               NA           <NA>

Other useful function for data exploration

#examine data structure

str(mosq.dat)
'data.frame':   159 obs. of  17 variables:
 $ id                 : num  36 36 37 37 38 38 39 39 40 40 ...
 $ municipality       : chr  "Lagodekhi" "Lagodekhi" "Lagodekhi" "Lagodekhi" ...
 $ village            : chr  "Lagodekhi nature reserve" "Lagodekhi nature reserve" "Lagodekhi nature reserve" "Lagodekhi nature reserve" ...
 $ destination        : chr  "Tree, bush, grass" "Tree, bush, grass" "tree,grass,toilets" "tree,grass,toilets" ...
 $ latitude           : chr  "41.844352" "41.844352" "41.842328" "41.842328" ...
 $ longitude          : chr  "46.2852763" "46.2852763" "46.284487" "46.284487" ...
 $ height             : num  580 580 564 564 558 558 573 573 494 494 ...
 $ temp               : chr  "28(32-23)" "28(32-23)" "28(32-23)" "28(32-23)" ...
 $ humidity           : num  59 59 59 59 57 57 59 59 51 51 ...
 $ wind               : num  10 10 10 10 10 10 10 10 10 10 ...
 $ trap_set           : chr  "23.07.24/8:25" "23.07.24/8:25" "23.07.24/8:55" "23.07.24/8:55" ...
 $ trap_collected     : chr  "26.07.24/7:05" "26.07.24/7:05" "26.07.24/7:25" "26.07.24/7:25" ...
 $ point              : chr  "36a" "36b" "37a" "37b" ...
 $ Ae.albopictus.count: num  NA NA NA NA NA NA NA NA NA 2 ...
 $ Ae.albopictus.sex  : chr  NA NA NA NA ...
 $ Cx.pipiens.count   : num  NA NA NA NA NA NA NA NA NA NA ...
 $ Cx.pipiens.sex     : chr  NA NA NA NA ...
#generate summary for each column of the dataset
summary(mosq.dat)
       id        municipality         village          destination       
 Min.   :36.00   Length:159         Length:159         Length:159        
 1st Qu.:47.00   Class :character   Class :character   Class :character  
 Median :58.00   Mode  :character   Mode  :character   Mode  :character  
 Mean   :61.72                                                           
 3rd Qu.:77.25                                                           
 Max.   :99.00                                                           
 NA's   :59                                                              
   latitude          longitude             height          temp          
 Length:159         Length:159         Min.   : 17.0   Length:159        
 Class :character   Class :character   1st Qu.:224.8   Class :character  
 Mode  :character   Mode  :character   Median :287.0   Mode  :character  
                                       Mean   :314.1                     
                                       3rd Qu.:439.8                     
                                       Max.   :580.0                     
                                       NA's   :71                        
    humidity          wind          trap_set         trap_collected    
 Min.   :36.00   Min.   : 0.000   Length:159         Length:159        
 1st Qu.:44.25   1st Qu.:10.000   Class :character   Class :character  
 Median :49.00   Median :10.000   Mode  :character   Mode  :character  
 Mean   :53.50   Mean   : 9.151                                        
 3rd Qu.:65.00   3rd Qu.:10.000                                        
 Max.   :79.00   Max.   :10.000                                        
 NA's   :73      NA's   :73                                            
    point           Ae.albopictus.count Ae.albopictus.sex  Cx.pipiens.count
 Length:159         Min.   : 1.00       Length:159         Min.   : 1.000  
 Class :character   1st Qu.: 1.00       Class :character   1st Qu.: 1.000  
 Mode  :character   Median : 2.00       Mode  :character   Median : 3.000  
                    Mean   : 2.46                          Mean   : 5.892  
                    3rd Qu.: 2.00                          3rd Qu.: 7.000  
                    Max.   :10.00                          Max.   :22.000  
                    NA's   :109                            NA's   :94      
 Cx.pipiens.sex    
 Length:159        
 Class :character  
 Mode  :character  
                   
                   
                   
                   
#use View() to open the dataframe in a separate window
View(mosq.dat)

Plotting you data

The $operator allow you to select specific columns from your data frame (mosq.dat). Let’s plot Ae. albopictus abundance using the plot() function:

plot(mosq.dat$Ae.albopictus.count)

This is the simplest way to quickly visualize your data. For a more flexible approach to plotting we will need to load the “ggplot2” package.

# run this line of code in case this is the first time that you are using ggplot2
install.packages('ggplot2')
# load the library
library(ggplot2)
ggplot(data = mosq.dat, # specify your data frame
       aes(x = c(x = c(1:length(Ae.albopictus.count))),
         y = Ae.albopictus.count)) + geom_point() + xlab('') + ylab('Aedes albopictus trap data')
Warning: Removed 109 rows containing missing values or values outside the scale range
(`geom_point()`).

There are five important steps that went into making that graph:

  • First, the ggplot() call tells R that we want to create a ggplot object

  • Second, the data = mosq.dat tells ggplot that everything we do should use the iris dataset

  • Third, the aes() specifies the aesthetics of the graph - what goes on the X and Y axes, but also any other data we want represented in our plot

  • Fourth, the + lets us add additional steps to our plot. Note that the + must always be at the end of a line - putting it at the start of a line will mess up your session! If you see a + in the console instead of a > after trying to plot something, this is most likely what happened - press your escape key to exit the command.

  • Finally, the geom tells ggplot what sort of graph we want. A geom is just the type of plot (or, well, the geometric object which represents data) - so geom_boxplot() generates a boxplot, while geom_col() makes a column chart. geom_point generates a scatterplot, but there are plenty of other options to choose from!

For more information on ggplot functions and aesthetics see: Chapter 2.3.

# Remember: you can check the documentation for every function using the following options
?ggplot # or
help(ggplot)

Working with times and dates in R

R has built-in classes to handle dates and times. The most common ones are:

  • Date for dates.

  • POSIXct and POSIXlt for dates with times (timestamps).

The standard data-time format for R is YYYY-mm-dd hh:mm:ss. This is the reason why rio did not automatically recognize the “trap_set” and “trap_collected” as POSIXct but instead read them as simple character vectors (NB: When R is confused it defaults to “character”). In the code bellow we use the as.POSIXct() function to transform the character vectors into POSIXct.

mosq.dat$trap_set.posix <- as.POSIXct(mosq.dat$trap_set, format = '%y.%m.%d/%H:%M') # convert the trap-set time to POSIXct and add as new column

mosq.dat$trap_collected.posix <- as.POSIXct(mosq.dat$trap_collected, format = '%y.%m.%d/%H:%M') # convert the collection time to POSIXct and add as new column

Common formatting symbols:

  • %Y - Year with century (2024)

  • %y - Year without century (24)

  • %m - Month (01-12)

  • %d - Day of the month (01-31)

  • %H - Hour (00-23)

  • %M - Minute (00-59)

Leaflet: a glimpse into visualizing spatial data in R

install.packages('leaflet')
library(leaflet)
leaflet(mosq.dat) %>%
  addTiles() %>%
  addMarkers( ~longitude, ~latitude,  # Longitude and Latitude columns
    popup = ~village  # Add popups with the name in the "village"column
  )

Examine error: if we look at the str(mosq.dat) command again, we will see that the longitude and latitude values are read as character but leaflet requires them to be numeric. We can quickly fix this with:

mosq.dat$longitude <- as.numeric(mosq.dat$longitude) # convert chr to num
mosq.dat$latitude <- as.numeric(mosq.dat$latitude) # convert chr to num
leaflet(mosq.dat) %>%
  addTiles() %>%
  addMarkers( ~longitude, ~latitude,  # Longitude and Latitude columns
    popup = ~village  # Add popups with the name in the "village"column
  )
Warning in validateCoords(lng, lat, funcName): Data contains 69 rows with
either missing or invalid lat/lon values and will be ignored