Lesson 6 · Working with data
Change data
Make new columns, recode values and deal with missing data.
Set up
library(tidyverse)
students <- read_csv("data/students.csv", show_col_types = FALSE)mutate(): add a column
| ID | Wellbeing_T1 | Wellbeing_T2 | Change |
|---|---|---|---|
| S001 | 5.00 | 5.00 | 0.00 |
| S002 | 1.33 | 1.33 | 0.00 |
| S003 | 3.33 | 4.33 | 1.00 |
The new column is calculated from other columns, for every row.
students %>%
mutate(Change = Wellbeing_T2 - Wellbeing_T1) %>%
select(ID, Wellbeing_T1, Wellbeing_T2, Change) %>%
head(3)# A tibble: 3 × 4 ID Wellbeing_T1 Wellbeing_T2 Change <chr> <dbl> <dbl> <dbl> 1 S001 5 5 0 2 S002 1.33 1.33 0 3 S003 3.33 4.33 1
Wellbeing_T1 and _T2 are wellbeing scores (1 to 7) at the start and end of semester.
Keep your changes
The code above only prints a result. To keep a new column, save it back with <-:
students <- students %>%
mutate(Change = Wellbeing_T2 - Wellbeing_T1)if_else(): two groups
students <- students %>%
mutate(Age_Group = if_else(Age >= 21, "21 and over", "Under 21"))
students %>% count(Age_Group)# A tibble: 2 × 2 Age_Group n <chr> <int> 1 21 and over 159 2 Under 21 141
if_else(question, value if yes, value if no). count() counts each value.
case_when(): recode
LearningStyle is stored as codes. Turn them into words:
students <- students %>%
mutate(LearningStyle = case_when(
LearningStyle == 0 ~ "Visual",
LearningStyle == 1 ~ "Kinaesthetic",
LearningStyle == 2 ~ "Auditory",
LearningStyle == 3 ~ "Reading/Writing"
))
students %>% count(LearningStyle)# A tibble: 4 × 2 LearningStyle n <chr> <int> 1 Auditory 48 2 Kinaesthetic 61 3 Reading/Writing 80 4 Visual 111
Each line is question ~ new value. It also works with ranges; .default catches everything else:
students %>%
mutate(Exam_Band = case_when(
ExamScore >= 70 ~ "High",
ExamScore >= 50 ~ "Middle",
.default = "Low"
)) %>%
count(Exam_Band)# A tibble: 3 × 2 Exam_Band n <chr> <int> 1 High 135 2 Low 27 3 Middle 138
Missing values
sum(is.na(students$Sleep))
students %>% filter(is.na(Sleep)) %>% select(ID, Sleep)
students %>% drop_na(Sleep) %>% nrow()[1] 10 # A tibble: 10 × 2 ID Sleep <chr> <dbl> 1 S003 NA 2 S051 NA 3 S054 NA 4 S136 NA 5 S173 NA 6 S178 NA 7 S205 NA 8 S250 NA 9 S285 NA 10 S298 NA [1] 290
is.na()finds missing values.drop_na(Sleep)removes rows where Sleep is missing.- Usually it is enough to add
na.rm = TRUEwhen you summarise (next lesson).
Exercises
Two groups
Add a column Short_Sleep: "Yes" if a student sleeps less than 6 hours, otherwise "No". Save it and count each group. What happens to students with no sleep answer?
Show answerHide answer
students <- students %>%
mutate(Short_Sleep = if_else(Sleep < 6, "Yes", "No"))
students %>% count(Short_Sleep)# A tibble: 3 × 2 Short_Sleep n <chr> <int> 1 No 214 2 Yes 76 3 <NA> 10
Students with a missing Sleep get NA, which is right: we don't know.
Recode stress
Make Stress_Level: "Low" for stress 1 to 3, "Medium" for 4 to 7, "High" for 8 to 10. Count each level.
Show hintHide hint
Start with the highest: Stress >= 8 ~ "High", then Stress >= 4 ~ "Medium", then .default = "Low".
Show answerHide answer
students <- students %>%
mutate(Stress_Level = case_when(
Stress >= 8 ~ "High",
Stress >= 4 ~ "Medium",
.default = "Low"
))
students %>% count(Stress_Level)# A tibble: 3 × 2 Stress_Level n <chr> <int> 1 High 62 2 Low 30 3 Medium 208
Key points
mutate()adds or changes columns. Save withstudents <- students %>% ...if_else()for two outcomes,case_when()for more.is.na()finds missing values;drop_na()removes them.