## 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!