Module 3:Bringing the Data In (Importing
& Inspecting)
1. Working with Directories and RStudio Projects
Before R can import a file, it must know exactly where on your computer’s hard drives to look. the location
is called the Working Directory. If you tell R to [Link](“clinical_trial.csv”) but the R is looking in your
download folder while the file is in your “Document” folder, the code will crash.
Absolute vs. Relative Paths: Beginners write out th entire path (e.g
"c/User/YKBPSYCHOLOGY/PhD/clinical_trial.csv" ). Professionals set their working directory to
a specific project folder once, and then use relative paths (e.g., just "clinical_trial.csv" ).
The Commands:
getwd(): Ask R, where are you currently looking?
setwd(“path/to/folder”): Commands R to look in this specific folder.
Advanced Pro-Tip (Future Concept): In modern R, we actually avoid setwd() entirely by using RStudio
Projects ( .Rproj files), which automatically anchor your working directory to the folder they live in,
ensuring your code works on any computer. We will discuss about it later.
Importing Data: The [Link]() functon.
The most universal format for scientific data is .csv . To bring this into R, we use the [Link]() function
and assign the output to a data frame object.
For example, we are running a trial testing a new intervention for Major Depressive Disorder (MDD). You
have a file named mdd_biomarkers.csv containing participant IDs, their biological Cortisol levels (in
nmol/L), and their Hamilton Depression Rating Scale (HAM-D) scores.
# standard Import
clinical_data <- [Link]("mdd_biomarkers.csv")
# ADVANCED IMPORT (Injecting Future Complexity)
# Real clinical data is messy. Sometimes a blood draw fails, or a patient skips a
question.
# We tell R immediately to treat blank spaces ("") and the number 999 as "NA" (Mis
sing Data).
# We also force R to automatically turn character columns (like "Treatment" / "Con
trol") into Factors.
# clinical_data <- [Link]("mdd_biomarkers.csv",
# [Link] = c("NA", "", "999"),
# stringsAsFactors = TRUE)
3. Inspecting the Data: The Clinical Diagnostic
once th data is in your Environment pane, you never click it to view the whole thing like an Excel sheet. If
you have 50,000 biological samples, trying to print that will crash your computer’s memory. Instead, we
use diagnostic functions to peek at the data’s anatomy.
Here are th four essential function you run the absolute second a dataset enter R:
1. head(clinical_data, n=5): Print only the first rows of your data frame. This is a quick visual sanity
check. Are the columns lined up correctly?
head(clinical_data, n=5)
## Participant_ID Cortisol_nmol_L HAM_D_Score
## 1 P001 492.22 16
## 2 P002 438.25 20
## 3 P003 505.05 20
## 4 P004 579.46 18
## 5 P005 430.10 21
2. tail(data_name, n) : Shows the absolute bottom n rows. Why? Because sometimes Excel files
have random summary statistics accidentally typed at the very bottom of the sheet. tail()
catches this before it ruins your analysis.
tail(clinical_data, n=5)
## Participant_ID Cortisol_nmol_L HAM_D_Score
## 96 P096 325.60 23
## 97 P097 475.17 18
## 98 P098 472.19 22
## 99 P099 450.43 22
## 100 P100 430.06 17
3. dim(clinical_data): Returns the dimensions as a vector of length 2: [Rows, Columns]. e.g., [1] 150 4
means 150 patients, 4 variables.
dim(clinical_data)
## [1] 100 3
4. str(clinical_data): The most important function. It shows the “structure”. It lists every column and tell
you its Atomic Data Type (Numeric, Factor, Logical). If your Cortisol column says chr (character)
instead of num, you know immediately your data is corrupt and needs cleaning.
str(clinical_data)
## '[Link]': 100 obs. of 3 variables:
## $ Participant_ID : chr "P001" "P002" "P003" "P004" ...
## $ Cortisol_nmol_L: num 492 438 505 579 430 ...
## $ HAM_D_Score : int 16 20 20 18 21 23 29 22 23 21 ...
5. summary(clinical_data): Generates instant descriptive statistics (min, median, mean, max) for every
numeric column, and counts the groups for factor columns.
summary(clinical_data)
## Participant_ID Cortisol_nmol_L HAM_D_Score
## Length:100 Min. :227.3 Min. :14.0
## Class :character 1st Qu.:398.9 1st Qu.:18.0
## Mode :character Median :439.2 Median :22.0
## Mean :441.2 Mean :21.6
## 3rd Qu.:484.5 3rd Qu.:24.0
## Max. :607.4 Max. :32.0
4. The Extraction Operator ($)
If you don’t want to summarize the whole data frame, and only want to look at the HAM_D_Scores, you
can extract a single column from data frame using $ symbol. This rips the column out of the 2D data frame
and returns it you as a 1D Vector.
# Extract just the HAM-D column and calculate its mean
# [Link] = TRUE is a future concept: it tells R to "Remove NAs" before calculating,
# otherwise one missing patient will make the entire mean return as NA.
mean_depression <- mean(clinical_data$HAM_D_Score, [Link] = TRUE)
print(mean_depression)
## [1] 21.6
Function What it does PhD-Level Use Case in Clinical
Bio-Psychology
getwd() Returns current file path Verifying R is looking in your
secure lab folder.
[Link]() Imports external file into a Data Loading your raw biological assay
Frame results.
str() Displays internal structure and Checking if R misclassified
data types numeric cortisol data as text.
summary() Provides rapid descriptive Checking for impossible data
statistics (e.g., a negative anxiety score).
$ The Extraction Operator Pulling out a specific biomarker
column for an isolated t-test.
Your Exercise
You have just received a dataset from a colleague in your clinical lab. The file is named
sleep_apnea_study.csv . It contains clinical data tracking sleep efficiency and biological stress markers.
Write the R code to execute the following comprehensive data intake protocol:
1. Import the dataset into an object named sleep_data .
Complexity requirement: Inside your [Link]() function, add the argument to ensure that
any missing data labeled as "Missing" or "-1" is properly converted to R’s official NA
format.
sleep_data <- [Link]('sleep_apnea_study.csv',
[Link] = c("Missing", "","-1"))
sleep_data$Gender <- [Link](sleep_data$Gender)
sleep_data$Group <- [Link](sleep_data$Group)
2. Run the specific function that will display the fundamental architecture and atomic data types of
every column in sleep_data to ensure it loaded correctly.
str(sleep_data)
## '[Link]': 50 obs. of 12 variables:
## $ PatientID : chr "P001" "P002" "P003" "P004" ...
## $ Age : int 63 53 39 67 32 45 63 43 47 35 ...
## $ Gender : Factor w/ 2 levels "F","M": 2 2 2 2 1 2 1 2 2 2
...
## $ BMI : num 22.8 27.6 32.9 32 35.5 29.7 44.9 23.4 26 2
7.7 ...
## $ SleepEfficiency : num 69.8 91.8 68.4 65.1 77.1 94.5 68.5 83.5 86.
7 68.3 ...
## $ TotalSleepTime_hours : num 7.9 7.2 4.4 4.8 8.5 7 4 4.5 7.3 4 ...
## $ ApneaHypopneaIndex : num 51.2 17.7 23.1 51.1 19 10.2 33.4 56.2 41.8
34.2 ...
## $ CortisolLevel_ug_dL : num 26.9 24.2 21.8 19.1 15.1 ...
## $ HRV_ms : int 86 84 52 59 93 62 63 48 32 31 ...
## $ StressMarker_CRP_mg_L: num 7.5 2.8 4.1 5.6 5.2 4.2 3.3 1.4 1 9.6 ...
## $ BloodPressure : chr "159/90" "118/98" "126/69" "125/78" ...
## $ Group : Factor w/ 4 levels "Control","Mild",..: 3 2 4 2
3 2 4 2 1 1 ...
3. Advanced stretch: Using the $ extraction operator, write the exact code to calculate the
summary() of only the column named blood_pressure .
library(tidyr)
sleep_data <- separate(data = sleep_data,
col = BloodPressure,
into = c("Systolic", "Diastolic"),
sep = "/",
convert = TRUE)
summary_systolic <- summary(sleep_data$Systolic)
print("--- Systolic Summary ---")
## [1] "--- Systolic Summary ---"
print(summary_systolic)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 100.0 112.5 133.0 131.6 149.0 159.0
summary_diastolic <- summary(sleep_data$Diastolic)
print("--- Diastolic Summary ---")
## [1] "--- Diastolic Summary ---"
print(summary_diastolic)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 62.00 72.25 82.50 81.20 90.00 98.00
Introducing Packages.
Base R is brilliant, but it only knows how to read plain, unformatted text files (like .csv or .txt). It does not
natively knows how to read proprietary, heighly formatted files like Excel ( .xlsx ) or SPSS ( .sav ).
To read those, we must download Packages. Think of Base R as a brand-new smartphone. It has core
functions (calling, texting), but if you want to navigate traffic, you must download the Google Maps app.
Packages are the apps of the R world.
There is a strict, two-step protocol for using packages:
1. Download it once ([Link]()): You only do this one time per computer. It downloads the
toolkit from the internet to your hard drive. (You type this in the Console).
2. Active it every time (library()): Every time you open a new R script, you must tell R to pull the
package out of the hard drive and turn it on. (you type this at the very top of your Source script)
Handling different File Types.
Data is wild is messy, proprietary, and uniquely formatted. In your psychological research you will
encounter in psychological research.
Text and Tab Separated Files (.txt or .tsv):
Often, cognitive task software (like E-Prime) or biological sensor export data as raw text files, where
columns are separated by invisible “Tabs” instead of commas.
Function: [Link]() or [Link]() (base R)
The sep argument: you must tell R how the column are separated. For tabs, we use the
special character \t .
# Importing a tab-separated text file of raw biological markers
bio_markers <- [Link]("raw_biometrics.txt", sep = "\t", header = TRUE)
Microsoft Excel (.xls, .xlsx):
Excel files are complex. They contain multiple sheets, color coding and hidden macros. Base R
cannot read them. We must use the readxl pakage.
Package: readxl
Function: read_excel()
The sheet argument: An Excel workbook might have multiple sheet like Sheet 1 as “Patient
Demographics” and Sheet 2 as “Cortisol Levels”. You can specify exactly which sheet to
import.
`# Step 1 (Console): [Link](“readxl”) # Step 2 (Script): Load the package library(readxl)
Import strictly the second sheet of the Excel workbook
demographics <- read_excel(“hospital_database.xlsx”, sheet = 2)`
SPSS ( .sav )
Many psychology departments still rely heavily on SPSS. When you collaborate with senior
researchers, they will often send you .sav files. SPSS files are unique because they have deep
metadata (e.g., they store both the number 1 and the label "Severely Depressed"
simultaneously).
Package: haven (Built specifically to translate SPSS/SAS/Stata files).
Function: read_sav()
`# Step 1 (Console): [Link](“haven”) # Step 2 (Script): Load the package library(haven)
Import the SPSS file preserving all clinical labels
legacy_data <- read_sav(“old_clinical_trial.sav”)
Summary Table
Source Format Required Package Import Function Key Arguments to
Remember
.csv None (Base R) [Link]() [Link] = c("")
(Catch missing data)
.txt / .tsv None (Base R) [Link]() sep = "\t" ,
header = TRUE
.xlsx (Excel) readxl read_excel() sheet = 1 (Specify
which tab)
.sav (SPSS) haven read_sav() Preserves SPSS variable
labels automatically
Exercise
You are a lead researcher taking over an ongoing study on Transdiagnostic Vulnerabilities (specifically
looking at rumination and anxiety). The data was collected by a hospital in an Excel workbook named
vulnerability_study.xlsx .
The data you need is specifically located on Sheet 3 of that Excel file.
Write the complete R script (from top to bottom) to do the following:
1. Activate the necessary package required to read Excel files.
library(readxl)
2. Import the data from Sheet 3 of vulnerability_study.xlsx and save it to an object named
clinical_rumination .
clinical_rumination <- read_excel("vulnerability_study.xlsx", sheet = 3)
3. Write the function that will verify the dimensions (row count and column count) of the dataset.
dim(clinical_rumination)
4. Write the function that will reveal the atomic data types (numeric, character, etc.) of every column.
str(clinical_rumination)
5. Advanced: Using the extraction operator ( $ ), write the exact code to calculate the mean() of a
column named rumination_score . Be sure to include the argument that prevents missing data
( NA ) from breaking the calculation.
rumination_score_mean <- mean(clinical_rumination$rumination_score, [Link] = TRUE)