## Welcome to R!
# If you're reading this then you have decided that you want to learn more about R and how to code in this language.
# This workshop will take the beginning steps on how to code in R.
# Once we have our feet wet, we will do a short example.
# R is an "object-oriented language". What that means is R is a program that is based on "objects" (or "variables") which can contain data.
# Objects works with your code to run rudimentary or complex methods or analysis.
#### Objects ####
# Let's take a look at some Objects in R. An Object can be one of a handful of types: character, numeric, integer, boolean.
# To make an object, type the object name and assign it a value using "<-" or "="
# You'll notice that a character object is made with quotations, integers have a "L" at the end, and boolean show up as blue.
# Object Naming Convention: Must start with a letter, case sensitive, can add ".", "_"
# To view the Object, simply type the Object name in your code and hit run
# Object Types
# We saw above some of the data types in R
# Specific object types are important in R because it allows for certain mathematical, relational, or logical operations to be applied.
# For example, you don't want to add a character object to a boolean object
NumericObject <- 1920232
Character_Object <- "Hi, I'm a Character Object"
Boolean.Object <- TRUE
typeof(Character_Object)
#Activity 1
# Make your own Objects called My_Birth_Month_Num and My_Birth_Month_Text
# Assign them the appropriate numeric and character values
#### Data Types ####
# Like Objects, Data Structures have different types as well.
# As shown in the slides, we have Vectors, Lists, and Data Frames, but there are a few other data types as well such as matrices, arrays, tibbles, and more.
# Look at the five data types below and print them to see their differences.
Vector1 <- c(1,2,3)
Vector2 <- c(1:10)
Vector3 <- c("Cat", "Dog", "Fish")
List1 <- list(Animal= c("Dalmations", "Dwarves", "Shreks"), Count=c(101, 7, 1))
City <- c("Ottawa", "Montreal", "Calgary", "Edmonton", "Toronto", "Vancouver", "Victoria", "Whitehorse")
Province <- c("ON", "QC", "AB", "AB", "ON", "BC", "BC", "YT")
Is.Capital <- c(TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE)
Population <- c(994837, 1780000, 1336000, 981280, 2731571, 631486, 85792, 25085)
Square.Kilometres <- c(2790.30, 365.65, 825.56, 685.25, 630.20, 114.97, 19.47, 416.54)
Median.House.Value <- c(400148, 380419, 450338, 390262, 601922, 1102843, 501002, 384194)
DataFrame1 <- data.frame(City, Province, Is.Capital, Population, Square.Kilometres, Median.House.Value)
DataFrame1
#### Indexing ####
# When you want to only grab part of a vector, matrix, dataframe or any other data type, you will need to index it.
# The easiest way is to use square brackets: [].
# For a vector, you simply type the vector name followed by square brackets and the value index position.
# For a two dimensional object, you can grab a specific value by typing in the row value followed by the column value: [row, column].
# You can grab a row or column of the dataframe by typing the row or column number and a blank such as:
# row one: [1,] or for column four: [,4]
# With dataframes and lists, you can also grab specific columns or items by using the dollar sign $ and typing the column name.
#Vector:
Vector1[1]
#Dataframes:
DataFrame1[1,2]
DataFrame1[,2]
DataFrame1[1,]
DataFrame1[,c(1,3)]
DataFrame1$Population
#Lists:
List1$Animal
#Activity 2
# Part 1 - Index DataFrame1 to print (show in console) the column Square.Kilometres
# Part 2 - Print the land area in Square Kilometres for the city of Ottawa
#### Functions ####
# Functions are the lifeblood of R. Each function requires takes some input, does some work to it, and outputs something else.
# Each function has a name and requires some arguments.
# For example, the mean() function requires the argument of what values to take the mean of.
# You can use a new object to store the results of a function.
# You can also use the function() function to make your own functions!
# Some Functions:
print("Hello World!")
mean(DataFrame1$Population)
Population.Median <- median(DataFrame1$Population)
strsplit("Let's Split this String!", split = " ")
String <- "Let's Split this String!"
strsplit(String)
# Getting Help:
help(strsplit)
?strsplit
#Make your own functions:
Fahrenheit.From.Celsius <- function(Celsius){
Fahrenheit <- Celsius*9/5 +32
return(Fahrenheit)
}
Fahrenheit.From.Celsius(Celsius = 20)
##Activity 3
#Hint: Google if you need to figure out the correct function for a specific task
#Using DataFrame1:
#Part 1 - Get the average Land area (Square.Kilometres)for all of the cities
#Part 2 - What is the largest (maximum) land area represented in the dataset?
#Part 3 - What is the smallest (minimum)land area represented in the dataset?
#### Operators ####
# R has many operators which allow you to carry out mathematical and relational operations.
# The simplest use of R is to use it as a calculator: Add, Subtract, Multiply, Divide, etc
# R also has relational operators such greater than, less than, or equals to, etc
#Mathematical Operators:
8 + 9
2 * 7
3/9
DataFrame1$Population * 5
#Relational Operators:
8 == 9
8 != 9
2 < 100
50 >= 18
#Activity 4 - Combining what we learned
#Using DataFrame1:
#Part 1 - Add the column Pop.Density to DataFrame1 with the population density for each city (population per square kilometer)
#Hint 1: There is no function to calculate population density. Use mathematical operators.
#Hint 2: Use $ to append a new column to a dataframe: The beginning of your statement should look like this:
DataFrame1$Pop.Density <-
#Part 2 - What is the lowest population density in our dataset?
min(DataFrame1$Pop.Density)
#Finishing the analysis
plot(DataFrame1$Median.House.Value,DataFrame1$Pop.Density)
text(DataFrame1$Median.House.Value,DataFrame1$Pop.Density,labels = DataFrame1$City, pos = 3)
cor(DataFrame1$Median.House.Value, DataFrame1$Pop.Density)
#### Conditional Statements ####
# Like in many other programs, R allows for conditional functions such as IF Statements or If-Else. We have seen () and [], now we will see {}.
#If Statement:
x <- 10
if(x < 100){
print("It's less than 100")
}
#If-Else Statement:
x <- 546
if(x < 100){
print("It's less than 100")
} else {
print("It's NOT less than 100")
}
#Ifelse Statement:
?ifelse
ifelse(DataFrame1$Population < 1000000, "Yes", "No")
DataFrame1$Less.Than.Million <- ifelse(DataFrame1$Population < 1000000, "Yes", "No")
DataFrame1
#### Loops ####
# Looping, cycling or iterating are just replicating instructions throughout a set of numbers. It is nothing more than automating a multi-step process by running steps in a batch process.
# A "For Loop" runs for a specific numeber of times.
# A "While Loop" runs until a condition is met, however, we won't look at While Loops now.
#For Loops:
for (i in 1:10){
print(i)
}
for (j in 2:7){
num <- j*j
print(num)
}
#### Packages ####
# Packages are what make R so great.
# There is pretty much a package for everything, and if there isn't then someone is probably working on one as we speak.
# Packages contain functions and sometimes data created by the community.
# The CRAN (Comprehenisve R Archive Network) repository stores the most used packages.
# When you find a good package online that you want to use, you have to install it the first time but you only have to do this once.
# Use the install.packages() function to install a package from CRAN.
# Once it's installed, you can load the package using the library() function.
# Once a package is loaded, you are free to run the functions that are in that package.
# Honestly, there's a package for everything!
# Let's install and load a package that we'll be using later
# When you install the package, you must put it in quotes, but not necessary when you load the package with library()
install.packages("ggplot2")
library(ggplot2)
#### Reading and Writing Data ####
# There is almost no type of data that R can't read and manipulate.
# We have seen text files, spreadsheets, geospatial data, word documents, and more already been shown, however, R can do so much more from image files to sound clips and just about anything else.
# The main types of data that you will encounter are text files or spreadsheet type files such as CSV (Comma-Seperated Values).
# Base R is able to read these files with the readLines() and read.csv() functions.
# If there is a data type that you want to read into R and don't know how, do a Google search and there will be a package to help you!
# Let's load the data that we will be using later and keep it as an object
# It's a csv file so we'll be using the read.csv() function
GapData <- read.csv("G:/R Workshops/Intro Workshop/GapminderData.csv", stringsAsFactors = FALSE)
GapData <- read.csv("C:/Users/christophershoniker/Downloads/R May 27/GapminderData.csv", stringsAsFactors = FALSE)
#### Let's play with some data! ####
# Before we load any data, let's set our Working Directory.
# The Working Directory is a main folder that R will look into first for data, or R scripts that you may call upon
# Where's my Working Directory?
getwd()
# To set your Working Directory:
setwd("G:/R Workshops/Intro Workshop")
setwd("C:/Users/christophershoniker/Downloads/R May 27")
# To check your Working Directory:
getwd()
#Now let's use read.csv() to read our data into R and save it as an object
GapData <- read.csv("GapminderData.csv", stringsAsFactors = FALSE)
#### Checking your Data ####
# Once your data is loaded into R, you should check it to make sure it loaded properly.
# Additionally, you should check to see what the column names are, if there are missing values, and how the data is structured (what data types do you have).
#Let's take a look at our data
#To look at the first entries use the head() function,
#By default head() will show you the first 6 rows
head(GapData)
#Or to look at the last entries use:
tail(GapData)
#We can also open up the full data in spreadsheet form by:
View(GapData)
#We can get more information by using the summary() function:
summary(GapData)
#We can check the data type of individual columns by using class():
class(GapData$year)
#We can see the different countries listed using the unique() function:
unique(GapData$country)
#Add to see how many unique countries there are, we can check by looking at how long
#unique(GapData$country) is by applying the length() function
length(unique(GapData$country))
#Let's see how many different countries for each continent there are using table():
table(GapData$continent)
NumberOfYears <- length(unique(GapData$year))
table(GapData$continent)/NumberOfYears
#Finally, Let's check to see if we have any missing values, called NA's in R
sum(is.na(GapData))
#### Create a New Column ####
# If we want to create a new column, it's very simple.
# Like you would with a new object, type out the name and apply some information to it, however, here we call on the dataset GapData and use the $ to set a new column with whatever name we want.
#We've now inspected our data and can now play with it
#Let's say we want to make a new column using data from existing columns
#Let's make a new column for Population but in Millions
#We'll call the new column PopMillions
GapData$PopMillions <- GapData$pop / 1000000
#Now let's check our data to see if it made the correct column
head(GapData)
#That was easy!
#### Subsetting our Data ####
# There are a few ways to subset our data.
# We have already learned about indexing so we will use that way first.
# Secondly, we will use the subset() function to grab a specific subset.
# There are many other ways in R to grab a portion of your data, however, we will stay with only these two for this tutorial.
#What if we're only interested in some of our data, say only Asian countries
#We can take a subset in multiple ways
#First, let's use what we learned about indexing to make a new all-Asian dataset
Asia <- GapData[GapData$continent == "Asia",]
head(Asia, n=15)
#Let's take a look at what is actually going on here:
head(GapData$continent == "Asia", n=62)
#The expression GapData$continent == "Asia" returns a boolean vector of Trues and Falses
#If the row is TRUE, then it keeps that row for the new dataframe otherwise it removes it
#That seemed to work, we can look at our global environment to see that Asia has only 396
#observations which is far less than the 1704 in GapData
#We could also check this using the nrow() function
nrow(Asia)
nrow(GapData)
#Another way of grabbing a subset of data is to use the subset() function
#Let's take a look at what the subset() function does first
?subset
Asia2 <- subset(GapData, GapData$continent == "Asia")
nrow(Asia) == nrow(Asia2)
#Lastly, let's say we want a dataframe of specific countries
#Again, there are a couple ways to do this, but we'll do it this way
#First make a vector of the countries that we want:
CountryVector <- c("Canada", "Mexico", "China", "Vietnam", "South Africa")
#Now, index like we did before:
UniqueCountries <- GapData[GapData$country %in% CountryVector,]
head(UniqueCountries)
#Lastly, we can index on multiple conditions as well using "&" and "|" for "and" and "or"
CanadaRecent <- GapData[GapData$country == "Canada" & GapData$year > 1980,]
CanadaRecent
#### Analyzing our Data ####
# Now that our data is organized and clean, we can start to look at it.
# Simple analysis like finding the mean or median for an entire column is quite simple, but the aggregate command lets use get statistics for specific groups.
#Let's now analyze some of the data
#Let's find the mean and median life expectancy for each year
aggregate(GapData$lifeExp, by = list(GapData$year), FUN = mean)
aggregate(GapData$lifeExp, by = list(GapData$year, GapData$continent), FUN = mean)
aggregate(GapData$lifeExp, by = list(GapData$year), FUN = median)
#Or we could do it this way with the ~:
aggregate(lifeExp ~ continent, GapData, median)
aggregate(lifeExp ~ continent, subset(GapData, GapData$year == 2007), median)
aggregate(lifeExp ~ year, GapData, median)
#### Visualizing our Data ####
# Now that we've analyzed some of our data, let's make some visualizations.
# Base R allows you to make very quick and simple plots that help you see your data.
# The simplest plots are histograms and scatterplots. We'll make one of each below.
#We've looked at some of our data so now let's make some plots
#R has base functions to plot your data using plot() or boxplot() or hist() or many others
#Let's make a histogram of GDP per capita in 2007
hist(subset(GapData$gdpPercap, GapData$year ==2007), breaks = 80)
#Let's now do a scatterplot of the logarithm of GDP per capita versus Life Expectancy
plot(x=log(subset(GapData$gdpPercap, GapData$year ==2007)), y=subset(GapData$lifeExp, GapData$year ==2007))
#### Using GGplot to Make Nicer Visulaizations ####
# Base R graphics aren't very pretty. Sure, there's addons and additional things that we can do, but the main visualization workhorse of R is the ggplot2 package.
# We've already installed and loaded the package, so now let's put it to work.
# We'll re-make the two plots from above with ggplot and check the differences.
# GGplot works a little different in that we set a ggplot() statement and then add additional themes and information on using the + sign.
# It takes a little while to get used to and learns about all the different options, but ggplot allows for a lot of customization and features.
# Ok, so we're able to visualize our data but these aren't very nice and they don't give a lot of information
# Luckily, R has many packages which are great for visualizing data
# Remember, we've already installed and loaded one package called ggplot2
# ggplot2 (geometry of graphics) is an awesome package which gives a plethora of options to visualize your data and customize those visulalizations
# It works a bit differently than the base R plots and takes some time to get used to but is a powerful tool
#First let's load a special file for colouring our countries
country_colors2 <- read.csv("Country_Colors.csv")
country_colors <- as.vector(country_colors2$x)
names(country_colors) <- country_colors2$X
#Let's remake our histogram with ggplot2:
ggplot(subset(GapData, GapData$year ==2007), aes(gdpPercap)) +
geom_histogram(bins = 80, fill="darkorchid4") +
ggtitle("2007 GDP Distribution across Countries") +
theme(plot.title = element_text(hjust = 0.5)) +
xlab("GDP per Capita") +
ylab("Count")
#That looks much nicer
#GGplot works by starting with a ggplot() function where we call out our data and aesthetics that we want to plot
#Then we add additional information such as the plot type (here it's a histogram), title, themes, labels, and much much more
#Let's replot our scatterplot from earlier
GapData2007 <- subset(GapData, GapData$year == 2007)
country_colors <- country_colors
ggplot(GapData2007,
aes(x = log(gdpPercap), y = lifeExp, color = country, size=pop)) +
geom_point(alpha = 0.7) +
theme_classic() +
scale_colour_manual(values = country_colors) +
theme(legend.position = "none") +
labs(title = '', x = 'GDP Per Capita', y = '') +
ggtitle("2007 GDP per Capita versus Life Expectancy") +
theme(plot.title = element_text(hjust = 0.5)) +
xlab("GDP per Capita") +
ylab("Life Expectancy")
#### Introducing GGanimate to Make GIFs ####
# Let's install a new package which allows us to animate our plots
#What if we want to add our Year variable to our visulaizations? We can make a gif to show the change over time
#We'll need another package to help us called gganimate (it's very similar to ggplot)
install.packages("gganimate")
library(gganimate)
install.packages("gifski")
library(gifski)
install.packages("png")
library(png)
#Now, lets run our code below to get a plot of GDP per Capita vs Life Expectancy over time
p <- ggplot(GapData, aes(gdpPercap, lifeExp, size = pop, colour = country)) +
geom_point(alpha = 0.7) +
scale_colour_manual(values = country_colors) +
scale_size(range = c(2, 12)) +
scale_x_log10() +
theme(legend.position = 'none') +
labs(title = 'Year: {frame_time}', x = 'GDP Per Capita', y = 'Life Expectancy') +
transition_time(year) +
ease_aes('linear')
animate(p, 100, 10)
#If we want to add a label for Canada, we can do that with a little bit more code:
p2Canada <- ggplot(GapData, aes(gdpPercap, lifeExp, size = pop, colour = country)) +
geom_point(alpha = 0.7) +
geom_text(data = subset(GapData, GapData$country == "Canada"), aes(gdpPercap, lifeExp, label = country)) +
scale_colour_manual(values = country_colors) +
scale_size(range = c(2, 12)) +
scale_x_log10() +
theme(legend.position = 'none') +
labs(title = 'Year: {frame_time}', x = 'GDP Per Capita', y = 'Life Expectancy') +
transition_time(year) +
ease_aes('linear')
animate(p2Canada, 100, 10)
# That's it!