This lab will guide you through (1) reading in data from your computer, (2) examining their summary statistics including mean, median, variance, and range, and (3) drawing some basic charts and graphs to visualize our data. In specific, materials in this document include:
| Functions | Tasks |
|---|---|
getwd() |
Print the current working directory |
setwd() |
Set the working directory to the specified path |
dir() |
Returns a character vector of names of files and folders in the current wd |
read.csv() |
Read in files with ‘.csv’ extensions |
head() |
Return the first few elements or rows (usually 6) |
sum() |
Return the sum of all elements |
length() |
Returns the count of elements. Works for vectors and lists |
summary() |
Returns central tendency statistics for the provided R object |
var() |
Returns variance of a vector, matrix, or data frame |
sd() |
Returns standard deviation of a vector |
table() |
Returns a table with labels and associated occurences of each label |
hist() |
Generates a histogram of the data in the given vector |
boxplot() |
Generates a boxplot of the data in the given data frame or a list |
When you open R-studio, your R session is located in one of the folders in your computer. This folder is called working directory. When you tell R to read a data using
read.csv()function, R starts looking for the file in the working directory. If your file is not there, R cannot find the file. You need to tell R where to find the file that you want to read.
Let’s see where your R session is currently located by using getwd() function. ‘wd’ here stands for working directory.
getwd()
## [1] "C:/Users/cod/Desktop/PhD Files/GRA & GTA/GTA/CP6025 Fall 2021/Week 2/Lab2"
Above is the folder your R session is currently in. Note that the path shown above is the current working directory of my (Gabriel’s) computer. Your current working directory may be different. Now, let’s tell R the location of the working directory that you want to work in (which is where the data is located) by using setwd() function.
Note that the folder names are separated by /, not \. If you copied and pasted a directory path from windows file explorer, you will need to change \ to /.
setwd("C:/Users/cod/Desktop/PhD Files/GRA & GTA/GTA/CP6025 Fall 2021/Week 2/Lab2")
You can also use the choose.dir() function to change your directory.
setwd(choose.dir())
Every time you open R-studio, you are initiating a new R session, and the working directory will revert back to where it first was. You will need to set the working directory to an appropriate folder every time you open R-studio.
Before we start using short-cut methods for calculating central tendencies, let’s try doing it manually. This will give you a better insight as to what is happening behind the scene.
First, let’s read some data in for the exercise. To see what files are in the new working directory, you can use dir() function.
dir() # When there is no argument inside the parenthesis, dir() returns the names of files or folders in the working directory. The output below is showing files and folders in my (Gabriel's) computer, and they may be different from yours.
## [1] "archive" "boxplot.png"
## [3] "boxplot2.png" "lab2.html"
## [5] "lab2.Rmd" "rsconnect"
## [7] "testdata.csv" "Week2_Lab_Descriptive.pdf"
## [9] "Week2_Lab_Descriptive.pptx"
If you see “testdata.csv”, you are in the right folder! Since we confirmed that R is in the right folder and can locate the file, let’s read it using read.csv() function and assign it to an R object called testdata. We can view the first few rows of the dataset using head().
# setwd("insert the path to the folder where data file is located")
testdata <- read.csv("testdata.csv")
head(testdata)
## X GISJOIN YEAR STATE COUNTY TRACT tot_age25 less_hs
## 1 1 G1300630040202 2013-2017 Georgia Clayton County 40202 1393 318
## 2 2 G1300630040203 2013-2017 Georgia Clayton County 40203 2134 306
## 3 3 G1300630040204 2013-2017 Georgia Clayton County 40204 2452 190
## 4 4 G1300630040302 2013-2017 Georgia Clayton County 40302 3520 1034
## 5 5 G1300630040303 2013-2017 Georgia Clayton County 40303 4072 1059
## 6 6 G1300630040306 2013-2017 Georgia Clayton County 40306 1959 781
## hs some_college college graduate hinc
## 1 581 338 123 33 31524
## 2 688 753 265 122 36786
## 3 877 825 371 189 39194
## 4 1347 855 235 49 33190
## 5 1319 1075 530 89 37236
## 6 430 567 169 12 27372
Another way to examine the data is by using str() function. Note that str() function not only shows what variables are in the data but also how many rows there are and what types of data each of the variables are.
str(testdata) # prints the dimension of the data in "the number of rows, the number of columns" format
## 'data.frame': 514 obs. of 13 variables:
## $ X : int 1 2 3 4 5 6 7 8 9 10 ...
## $ GISJOIN : chr "G1300630040202" "G1300630040203" "G1300630040204" "G1300630040302" ...
## $ YEAR : chr "2013-2017" "2013-2017" "2013-2017" "2013-2017" ...
## $ STATE : chr "Georgia" "Georgia" "Georgia" "Georgia" ...
## $ COUNTY : chr "Clayton County" "Clayton County" "Clayton County" "Clayton County" ...
## $ TRACT : int 40202 40203 40204 40302 40303 40306 40307 40308 40407 40408 ...
## $ tot_age25 : int 1393 2134 2452 3520 4072 1959 3098 3089 2421 4892 ...
## $ less_hs : int 318 306 190 1034 1059 781 979 1001 618 989 ...
## $ hs : int 581 688 877 1347 1319 430 1087 1127 914 1879 ...
## $ some_college: int 338 753 825 855 1075 567 787 703 582 1426 ...
## $ college : int 123 265 371 235 530 169 214 245 209 431 ...
## $ graduate : int 33 122 189 49 89 12 31 13 98 167 ...
## $ hinc : int 31524 36786 39194 33190 37236 27372 37064 25159 45768 37224 ...
Now the R object testdata contains the data from “testdata.csv”. testdata is a dataframe (similar to an Excel spreadsheet) with 514 rows and 13 columns (a.k.a. variables). For this exercise, we will only use one of them - the variable named hinc. This variable represents the median household income of the Census tracts (similar to neighborhoods) in the 4 counties around Atlanta.
In R, testdata$hinc means “Give me the variable named hinc in the dataset called testdata.” Here, $ operator extracts parts of an R object. If used with a data.frame, it extracts columns.
head(testdata$hinc)
## [1] 31524 36786 39194 33190 37236 27372
Second, let’s calculate the mean of testdata$hinc. Here is the equation for calculating mean: \(\bar{x} = \frac{1}{n}\left (\sum_{i=1}^n{x_i}\right )\). The first part of the equation we need to solve is \(\left (\sum_{i=1}^n{x_i}\right )\), which is mathematical way of saying “sum every element in x”. In R, this equation can be written as:
sum.hinc <- sum(testdata$hinc)
Note that we created an R object called sum.hinc by assigning the result of sum(testdata$hinc) into the object using <-. To see what is stored in sum.hinc, you can simply call the object.
sum.hinc
## [1] 34309653
Third, the equation \(\bar{x} = \frac{1}{n}\left (\sum_{i=1}^n{x_i}\right )\) suggests that sum.hinc needs to be multiplied by \(\frac{1}{n}\), where n is the number of elements in testdata$hinc. You can get the number of elements using length().
1 / length(testdata$hinc) * sum.hinc
## [1] 66750.3
There you have it! Let’s also use R function mean() to check if the manually calculated mean is correct.
mean(testdata$hinc)
## [1] 66750.3
Matches perfectly! It shows that, on average, typical households in Georgia makes about $67,000 per year.
This time we will calculate variance using the same testdata and the mean we just calculated. Like we did for mean, let’s break down the equation for variance and tackle it piece by piece. The equation is: \(\sigma_Y^2 = \frac {1}{n-1} \sum_{i=1}^n \left(Y_i - \overline{Y} \right)^2\)
First, let’s focus on \(\left(Y_i - \overline{Y} \right)^2\) part. The following code calculates it and stores it in an object called parenthesis .
parenthesis <- (testdata$hinc - mean(testdata$hinc))^2 # ^2 means to square it
head(parenthesis) # Prints the first six elements in parenthesis
## [1] 1240892047 897859135 759349541 1126293579 871093767 1550650327
Second, we are done with \(\left(Y_i - \overline{Y} \right)^2\) part. Now, we need to sum all numbers in this vector to finish \(\sum_{i=1}^n \left(Y_i - \overline{Y} \right)^2\) part.
sum.parenthesis <- sum(parenthesis)
sum.parenthesis
## [1] 671687216869
Third, the last thing we need to do is to divide sum.parenthesis by \(n-1\), where \(n\) is the number of elements in the vector. You can get the number of elements using length(). Let’s also use R function var() to see if the numbers match.
sum.parenthesis / (length(testdata$hinc) - 1)
## [1] 1309331807
var(testdata$hinc)
## [1] 1309331807
Matches perfectly again!
Instead of doing this every time we need to calculate mean, variance, etc., we can simply use base R function that does it all for us.
mean(testdata$hinc) # This function outputs mean of the given vector
## [1] 66750.3
var(testdata$hinc) # This function outputs variance of the given vector
## [1] 1309331807
sd(testdata$hinc) # This function outputs standard deviation of the given vector
## [1] 36184.69
summary(testdata$hinc) # This function outputs various descriptive statistics. Note that summary() sometimes rounds up the numbers!
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 9815 40153 58418 66750 84288 200179
NOTE using summary() to view the descriptive statistics can sometimes be misleading. This is because summary() rounds up the results (see the difference between mean(testdata$hinc) and the mean from summary(testdata$hinc)). If you need to generate precise statistics (e.g., for your option paper or thesis), I recommend using mean(), min(), max(), median(), etc. instead of summary().
Visualizing data you are about to crunch can give you invaluable insights about your data. The most popular and useful way to visualize variables include histogram and boxplot. Visualizing your data is a very important first step of any data analysis.
First, let’s visualize the distribution of the variable using hist(). This draws a histogram.
hist(testdata$hinc)
This histogram suggests that testdata$hinc is heavily skewed with a long tail to the right (=right-skewed). There are many Census tracts of which the median household income is around $50,000. There are a very small number of Census tracts that are super rich.
Also note that by including breaks = 5, you can make the bars wider, as shown below. But notice how having too wide bars obscure some details. Try different breaks to find out what number makes the histogram most informative.
hist(testdata$hinc, breaks = 5)
An interesting side note: Although a histogram and a barplot may look similar, they are very different. A histogram uses a continuous variable and requires only one variable. For example, if you have testdata$hinc, that is all you need for a histogram. However, creating a barplot requires a categorical variable (either nominal or ordinal) AND an associated quantity. For example, you can’t draw a barplot with testdata$hinc; you need another variable with which we can group testdata$hinc. See the barplot below for an illustration where I create a barplot of the number of Census tracts for each County.
We first need to count how many Census tracts there are in each county. table() function returns the unique category names (in this case, the names of counties stored in testdata$COUNTY) and the number of their occurences.
number.tract <- table(testdata$COUNTY)
number.tract
##
## Clayton County Cobb County DeKalb County Fulton County
## 49 120 143 202
In number.tract, We now have a categorical variable (Name of counties) and an associated quantity (the number of their occurences). The barplot can created in R by:
barplot(number.tract)
Second, boxplots are another way of visualizing the distribution. The image below shows how to interpret a boxplot.
Now let’s look at a boxplot of testdata$hinc.
boxplot(testdata$hinc)
It shows that (1) the median (the thick horizontal bar inside the box) is skewed downwards and (2) there are many outliers on the higher side of the distribution. Compare the shape of the boxplot with the histogram above and see how they correspond to each other.
Boxplot is very useful especially when your continuous variable (in our case, testdata$hinc) can be grouped by a categorical variable. Remember that testdata$hinc is the median household income of Census tracts in the 4 counties around Atlanta, including Clayton, Cobb, Dekalb, and Fulton County. That means, we can group the Census tracts into four groups based on what county they fall into.
In our testdata, we can draw a boxplot of hinc for different COUNTY.
boxplot(testdata$hinc ~ testdata$COUNTY)
Notice the testdata$hinc ~ testdata$COUNTY part in the code. This is R way of saying “draw a boxplot of testdata$hinc and group it by testdata$COUNTY”. A few notable things from the plot include (1) different counties have different median values, (2) Census tracts in Clayton County has relatively less dispersed distribution of median income, (3) Fulton County has the most widely dispersed distribution with many outliers, and (4) Dekalb County has the median similar to Fulton County but has distinctively many outliers.
Finally, the labels on the histrogram and boxplot are either missing or not so intuitive. Let’s make them more readable by adding some axis labels.
hist(testdata$hinc,
main = "Histrogram of Median Household Income of Four Counties Around Atlanta",
xlab = "Median Household Income",
ylab = "Frequency",
col = "skyblue")
boxplot(testdata$hinc ~ testdata$COUNTY,
main = "Boxplot of Median Household Income Grouped by County",
xlab = "County",
ylab = "Median Household Income",
col = c("yellow", "Grey", "orange", "pink"))