For this code-through I have chosen to explore a publicly available dataset called “College”. I work in higher education, so I wanted to choose a dataset that might have some of the same fields or topics that I encounter on a daily basis. I chose to download this dataset, manipulate it a little bit, create some basic visualizations that can be saved to local files, and then and then write separate dataframes to individual tabs on an excel sheet. This is a common process that I need to do in my job, and using R to help assist with this will be hugely beneficial for my workflow, standardization, and reproducibility.
Specifically, I will explain and demonstrate:
This topic is valuable because it walks through a ‘complete’ process that one might encounter on a regular basis. From accessing a data source, to familiarizing yourself with it, asking questions about it, manipulating it to be able to conduct analysis to answer those questions, creating basic visualizations that can be saved, and being able to save the output in still one of the most commonly used formats in many businesses and industries. It shows a basic complete cycle and puts everything together in one place.
The resources section and data file “college.csv” can be
found here.
Make sure you:
You will need several packages to be able to read the Google Sheet, as well as manipulate the data. Install the following packages using the install.packages() function, if you have not previously done so. If you have previously installed them, just call them using the “library()” function:
library(tidyverse) #this package contains the pivot_longer funtion for data manipulation
#library(googlesheets4) #reference on this package can be found here: https://googlesheets4.tidyverse.org/
library(dplyr) #We will need this for data manipulation
library(ggplot2) #we will need this for visualization
library(openxlsx) #we will need this for reading/writing Excel files
Of course you can and should name your dataset so that you’ll be able to easily call it moving forward. In this case, I’ve chosen to name it ‘mydata’.
Once your data is uploaded you should be able to ‘print’ your table like below:
When working with a new dataset, it’s important to spend some time familiarizing yourself with it. The first thing I like to do is just print a tibble or dataframe like above to get an overall understanding of what the table looks like.
The first thing I noticed in this dataset is that the first vector appears to have a strange name. In order to confirm the name, you can use the names() function:
## [1] "X" "Private" "Apps" "Accept" "Enroll"
## [6] "Top10perc" "Top25perc" "F.Undergrad" "P.Undergrad" "Outstate"
## [11] "Room.Board" "Books" "Personal" "PhD" "Terminal"
## [16] "S.F.Ratio" "perc.alumni" "Expend" "Grad.Rate"
The name for the first vector is not explanatory. You can rename
it like this:
## [1] "University" "Private" "Apps" "Accept" "Enroll"
## [6] "Top10perc" "Top25perc" "F.Undergrad" "P.Undergrad" "Outstate"
## [11] "Room.Board" "Books" "Personal" "PhD" "Terminal"
## [16] "S.F.Ratio" "perc.alumni" "Expend" "Grad.Rate"
The tibble shows there are 777 rows, or Universities, with data included in the dataset. There are also 19 columns that we can see from the dataset, and they are now named relatively meaningfully. Here are some questions that come to mind for possible analysis:
We can first create some new variables to answer the first four questions above:
mynewdata <- mydata%>%
group_by(University)%>%
mutate(total.cost=sum(Outstate,Room.Board,Books,Personal),accept.rate=Accept/Apps,enroll.rate=Enroll/Apps,enroll.yield=Enroll/Accept,priv.pub = case_when (Private == "Yes" ~ 'Private',Private == "No" ~ 'Public')) #Creating priv.pub also for use in later analysis, explained in next section
mynewdata
Some universities in this list are private and some are public. This is recorded in the second variable “Private”. The values in this vector are “Yes”, meaning Private, or “No”, meaning public. To make it easier to understand, I also created a new variable “priv.pub” that properly labels each as Private or Public.
So now that our data contains the metrics that we are interested in, we can begin answering our final question: *Is there a difference in the above things between private and public universities?
mynewdatasummary<-mynewdata%>%
group_by(priv.pub)%>%
summarise(count=n(),avg.cost=mean(total.cost),avg.apps.recvd=mean(Apps),avg.accept.rate=mean(accept.rate),avg.enrolltoapps.rate=mean(enroll.rate),avg.enrolltoaccept.yield=mean(enroll.yield))
mynewdatasummaryWhile this is a fairly small dataset and it’s relatively easy to compare the numbers in the table above, especially since we’ve transformed some of the values into proportions, we can also visualize the data.
First we can compare the total number of public and private universities:
And plot it into a bar graph:
#####If you want to save the output into a PNG, you must do step 1, step 3 and step 4#####
#####If you only want to create the visualization for your rmd/html and NOT save the viz, you only need to create the barplot and print
# Step 1: You must first open PNG graphics device (if you want to save it to PNG, if not then skip)
png(filename = "C:/Users/mlbrentl/Desktop/PEDAMS/Codethrough/appcountplot.png", width = 800, height = 600)
# Step 2: Create bar plot
appcountplot <- barplot(bardata$count,
names=bardata$priv.pub,
xlab='Institution',
ylab='Applications',
main="Total number of applications",
col = "cadetblue2")
# Step 3: Close the graphics device (if you opened the graphics device in step 1 above, if not then skip)
dev.off()## png
## 2
# Step 4: Display the plot in R Markdown (if you did Steps 1 and 3, the plot will not display in rmd/html without the knitr option)
knitr::include_graphics("C:/Users/mlbrentl/Desktop/PEDAMS/Codethrough/appcountplot.png")The code above also includes instructions for how to save the plot output into a PNG to be able to insert into your Excel file later.
We can also look at the numbers of applications received, accepted, and ultimately enrolled per institution type. In order to do this, we’ll need to go back to a previous version of the data that contains counts, not proportions:
mynewappdata<-mynewdata%>%
group_by(priv.pub)%>%
select(priv.pub,Apps,Accept,Enroll)%>%
summarise(count=n(),avg.1apps.recvd=mean(Apps),avg.2accept=mean(Accept),avg.3enroll=mean(Enroll))
mynewappdataThis format/structure will not allow us to visualize in a line graph, so we need to transform the dataset to a ‘long’ dataset. This means that we need to create more rows and less columns, basically. We can use the ‘pivot_longer’ function like below:
mynewappdatalong<-mynewappdata%>%
select(!count)%>% #we don't need the count of universities for the desired visualization, so we can exclude it
pivot_longer(
cols = !priv.pub,
names_to = "Status", #this changes the 'names' of each column in the previous dataset to a new variable that you name here
values_to = "count")%>% # this moves the values from the previous dataset into a new variable/column that you specify here
arrange(Status) #You can arrange the data differently so that it will plot correctly in your visualization. In this instance, I couldn't figure out how to get it arranged correctly without numbering the columns from before. Messy, but it worked!
mynewappdatalongThen we are able to use ggplot to create a line graph showing the two different institution type groups and their application/enrollment statuses:
appstatusplot<-mynewappdatalong%>%
ggplot()+
geom_line(mapping=aes(x = Status, y = count, group = priv.pub,col=priv.pub))+
scale_x_discrete(labels=c('Applications Received', 'Acceptance Letters Issued', 'Enrollments')) #to rename the x-axis labels
appstatusplot######If we want to save this to a PNG file for inserting into our Excel later, this is how we do it:########
# Save ggplot to a PNG file
ggsave(filename = "C:/Users/mlbrentl/Desktop/PEDAMS/Codethrough/appstatusplot.png",
plot = appstatusplot,
width = 8, height = 6)From this basic summary, we can learn several interesting things. First, there are far more Private Institutions in this dataset than Public, and the cost of the Private institutions is higher (no surprise). The number of applications that Public Institutions receive on average is a lot higher than the private institutions (also not that surprising). It’s interesting when you compare Enrollments for both institution types - the difference between enrollments and applications received at public universities is very different.
After manipulating the data, it is oftentimes useful to save the cleaned/manipulated datasets to a local file, either for sharing or for record-keeping purposes. This is a very common practice in my current position - certain colleagues are responsible for different populations of students and I often need to save filtered versions of a total dataset for each colleague to reference easily. I will now explain one way to do this.
Next, I need to write individual csv files for separate tabs that will be merged together.
#Total complete dataset
write.csv(mynewdata,"C:/Users/mlbrentl/Desktop/PEDAMS/Codethrough/CSVfiles/CompleteData.csv", row.names=FALSE)
#Private university dataset
write.csv(privatedata,"C:/Users/mlbrentl/Desktop/PEDAMS/Codethrough/CSVfiles/PrivateData.csv", row.names=FALSE)
#Public university dataset
write.csv(publicdata,"C:/Users/mlbrentl/Desktop/PEDAMS/Codethrough/CSVfiles/PublicData.csv", row.names=FALSE)
#Summary data
write.csv(mynewdatasummary,"C:/Users/mlbrentl/Desktop/PEDAMS/Codethrough/CSVfiles/SummaryData.csv", row.names=FALSE)# Specify the directory containing CSV files
csv_directory <- "C:/Users/mlbrentl/Desktop/PEDAMS/Codethrough/CSVfiles/"
# List CSV files in the directory
csv_files <- list.files(path = csv_directory, pattern = "\\.csv$", full.names = TRUE)
# Define Excel file path to be saved to
excel_file <- "C:/Users/mlbrentl/Desktop/PEDAMS/Codethrough/FinalCollegeDataset.xlsx"
# Create a new Excel workbook
wb <- createWorkbook()
# Loop through each CSV file and add its data to a new sheet in the Excel workbook
for (i in seq_along(csv_files)) {
# Read data from CSV file
data <- read.csv(csv_files[i])
# Sheet name based on file name
sheet_name <- gsub(".csv", "", basename(csv_files[i]))
# Add data to a new sheet in the workbook
addWorksheet(wb, sheetName = sheet_name)
writeData(wb, sheet = i, x = data)
}
# Save the Excel workbook
saveWorkbook(wb, excel_file)
In this process, we have also created a couple visualizations, and while I’m not sure of a way to get them directly embedded into the Excel file, we can save them as png files in the same filepath as the Excel sheet and then insert them manually. These steps were done above in the code chunks when creating the visualizations, so please reference how to do that above. Different plotting functions seem to have slightly different ways to get the images saved, so you might have to ask Google or ChatGPT exactly how to save your visualizations based on your specific plot function. As a reminder, if you want to include the visualizations in your excel sheet, you will need to manually insert them.
This code-through has shown how to use R to read a dataset from a local file, and shared some basic processes to explore, manipulate, and visualize a dataset to answer questions posed. Furthermore, it shows one way to save copies of the manipulated datasets into an Excel file, as well as a couple ways to save the visualizations to a local png file which can be manually embedded into the Excel sheet, if desired. While I’m sure there are much better ways to accomplish these things, I hope this shows a good example of a basis to work from moving forward.
Some extra resources used to assist in the making of this code-through:
Pivoting, Tidyr vignette https://cran.r-project.org/web/packages/tidyr/vignettes/pivot.html
geom_line in ggplot2, Plotly Graphing Libraries https://plotly.com/ggplot2/geom_line/
Set color by group in ggplot2, Statistics Globe https://statisticsglobe.com/set-color-group-ggplot2-plot-r