Rows: 2,724
Columns: 16
$ disease <chr> "Mening", "Mening", "Mening", "Mening", "Mening"…
$ region_id <chr> "R1", "R1", "R1", "R1", "R1", "R1", "R1", "R1", …
$ age_years <dbl> 1, 3, 0, 0, 2, 6, 55, 17, 3, 38, 3, 14, 14, 16, …
$ age_months <chr> NA, NA, "2", "5", NA, NA, NA, NA, NA, NA, NA, NA…
$ sex <chr> "M", "F", "F", "M", "M", "M", "M", "F", "M", "F"…
$ year <dbl> 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, …
$ key_date <chr> "1999-01-01", "1999-01-01", "1999-01-01", "1999-…
$ symptom_onset_date <chr> "1999-01-01", "1999-01-01", "1999-01-01", "1999-…
$ clinical_presentation <chr> "Sepsis", "Mening", "Mening", "Sepsis", "Both", …
$ death <chr> "No", "No", "No", "Yes", "No", "Yes", "Yes", "No…
$ country <chr> "ES", "ES", "ES", "ES", "ES", "ES", "ES", "ES", …
$ imported <chr> "No", "No", "No", "No", "No", "No", "No", "No", …
$ diagnostic_date <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ serogroup <chr> "B_NeisMen", "C_NeisMen", "C_NeisMen", "B_NeisMe…
$ type_of_case <chr> "Prim", "Prim", "Prim", "Prim", "Prim", "Prim", …
$ lab_confirmed <chr> "Yes", "Yes", "Yes", "Yes", "Yes", "No", "Yes", …
Variable Class
Session 3 practical exercises
Column names are now sorted. But a clean name does not mean the column contains the right type of data — and in R, type matters more than you might expect. A number stored as text cannot be used in calculations. A date stored as text cannot be used to compute time intervals or epidemiological weeks. R will not warn you about this automatically. It will just quietly produce wrong results, or throw an error at the worst possible moment.
So the second step of any cleaning pipeline is to check what R thinks each variable is, and fix anything that is wrong.
Part 2 · Inspecting variable types
You have already met names(). Now you need a function that shows you the type of each column at a glance. Run this on your cleaning object:
glimpse(imd_cleaning)You should see something like this:
Look at the type tags in angle brackets: <chr>, <dbl>, <lgl>. These are R’s way of telling you what it thinks each column is.
Action — Before reading on, look at the output and identify which columns have a type mismatch — where what R thinks the variable is does not match what it should actually be.
Action — Try out the other functions for examining data: str(), summary(), head()
| Tag | Type | Example |
|---|---|---|
<chr> |
Character (text) | "Male", "Narnia", "Yes" |
<dbl> |
Double (number) | 23, 1999, 3.5 |
<lgl> |
Logical | TRUE, FALSE, NA |
<date> |
Date | 1999-03-12 |
A column with dates showing as <chr> is one of the most common problems in real surveillance data. R sees "1999-03-12" as just a string of characters — it has no idea it represents a point in time.
Did you find the column with only missing values? This is interpreted as logical in R, independently of what kind of information we intended to put there
Part 3 · Fixing variables types
Fixing numbers
The age_months column is stored as <chr>. This means R cannot use it in any calculation. The fix is straightforward: inside a mutate(), you overwrite the column with its numeric version using as.numeric()
Remember that mutate() can modify existing variables
mutate(
variable = function(variable)
)Action — Add this mutate() to your cleaning pipeline to fix age_months, run it, and check glimpse() again. Did age_months change to <dbl>?
You will likely see this warning in your console:
Warning: NAs introduced by coercionDo not panic. This is R being honest with you. When R tries to convert a character column to numeric, it succeeds for values like "2" or "8". But some cells may contain text that cannot be converted — like a genuine missing value entered as blank or a data entry error. R converts those to NA and tells you about it.
In this dataset this is expected and correct behavior. Warnings are only that: warnings. They want you to be aware something happened that is not an error inherently
Fixing dates
Dates are the most common source of pain in surveillance data — and the most important to get right, since almost every epidemiological analysis depends on them.
Look at your glimpse() output again. Three date columns are stored as <chr>:
key_datesymptom_onset_datediagnostic_date
The lubridate package (part of tidyverse) provides a family of functions to convert text into real dates. The function name tells R what order to expect the date components:
ymd()→ year, month, day (e.g."1999-03-12")dmy()→ day, month, year (e.g."12/03/1999")mdy()→ month, day, year (e.g."03/12/1999")
Action — Check the actual values in your date columns to determine which format each one uses
Action — Add the three date conversions to your mutate(). Use the right function for each column based on what you observed.
"03/12/1999" is that the 3rd of December, or the 12th of March? Without knowing the format, R cannot tell. If you apply the wrong function, R may either return NA for every row, or worse — silently parse the dates incorrectly and give you plausible-looking wrong values.
Always check the raw values before converting. Always.
Action — After adding all conversions, run glimpse() one more time. Confirm that age_months is now <dbl> and that key_date and symptom_onset_date are now <date>. What about diagnostic_date?
Other functions for changing class
You just used two very relevant functions: as.numeric() and ymd() for numbers and dates. But other relevant functions exist and are needed:
as.character()transforms column values into textas.integer()alternative version for numeric transformationas.factor()a factor variable is slightly different, and will be covered further into the course- Many other
as.something()functions exist that cover topics beyond the course (matrix, tibbles, vectors, etc.)
What does glimpse() show you that head() does not?
A date column that has not yet been converted will appear in glimpse() as:
You run as.numeric() on a column and see “NAs introduced by coercion”. What does this mean?
“NAs introduced by coercion” is R being transparent, not alarming. When converting text to numbers, any value that cannot be parsed as a number — blanks, "unknown", stray letters — becomes NA. This is the correct behaviour. The question is always whether the number of new NAs is what you would expect given your data.
Which function would you use to convert the string "1999-03-12" to a date?
Exercise summary
Your columns now have the right types. Numbers are numbers, dates are dates. In E3 you will tackle the messier problem: categorical variables with inconsistent labels.
We used these functions for achieving our goal:
| Function | Package | What it does |
|---|---|---|
glimpse() |
dplyr | Shows column types and first values — your primary inspection tool |
mutate() |
dplyr | Creates or modifies columns |
as.numeric() |
base R | Converts a column to numeric; non-convertible values become NA |
ymd() / dmy() |
lubridate | Converts text to dates; function name = expected order of components |
This is the full mutate() block to add to your pipeline after the name-cleaning step:
# Change variables type
mutate(
age_months = as.numeric(age_months),
key_date = ymd(key_date),
symptom_onset_date = ymd(symptom_onset_date),
diagnostic_date = ymd(diagnostic_date)
)