First, we load some necessary libraries
library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(tidyr)
Loading data from google drive.
# here we run bash
gdown -q 1GxG6hXZwQ1NC7OcPdArKNeDLZDFHx1DN
df = read.csv('Ferguson2017.csv')
df
where the columns with dates are of type “character”:
df |> select(contains('Date'))
so we will modify them to the type “Date”
df |> mutate(across(contains('Date'), ~as.Date(., format='%Y-%m-%d'))) -> df
df
Now, we want to calculate the number of deaths and survivors by country
df |>
# we group by country and final status (dead/alive/NA)
group_by(Country, FinalStatus) |>
# and then count how many records we have per each grouping
# I also write .groups = 'drop' in order to avoid warning message in R
summarize(count = n(), .groups = 'drop') |>
# we transform long format to wide
# *please check what it means by commenting/uncommenting*
pivot_wider(names_from = FinalStatus, values_from = count) |>
# again grouping by country to calculate correctly Totals
group_by(Country) |>
# summing Alive/Dead/NAs which are of type "numeric"
mutate(Total = sum(c_across(where(is.numeric))),
`CFR, %` = Dead / Total * 100)
# note if I want to declare a new variable with non-traditional characters,
# I need to use `...`
# alternatively:
# CFR = Dead / Total * 100)
We could also write the last pipe in more obvious way:
df |>
group_by(Country, FinalStatus) |>
summarise(Count = n(), .groups = 'drop') |>
#drop_na() |>
pivot_wider(names_from = FinalStatus, values_from = Count) |>
mutate(`CFR, %` = round(Dead / (Alive + Dead) * 100, 2))
Calculating CFR for people who were hospitalized
df |>
# here we choose only people with *known* hospitalization status
filter(HospitalizedEver=='Yes') |>
group_by(Country, FinalStatus) |>
summarise(Count = n(), .groups = 'drop') |> #drop_na() |>
pivot_wider(names_from = FinalStatus, values_from = Count) |>
mutate(Total = sum(c_across(where(is.numeric))),
CFR = Dead / Total,
`CFR, %` = round(Dead / Total * 100, 2))
In more general way:
df |>
group_by(Country, FinalStatus, HospitalizedEver) |>
summarise(Count = n(), .groups = 'drop') |>
pivot_wider(names_from = FinalStatus, values_from = Count) |>
group_by(Country, HospitalizedEver) |>
mutate(Total = sum(c_across(everything()), na.rm=TRUE),
CFR = Dead / Total,
`CFR, %` = round(Dead / Total * 100, 2)) -> df_CFR_hosp
df_CFR_hosp
Again, if we want we can pivot the obtained data frame to the wide format for CFR. However, we would also need to the id_cols:
df_CFR_hosp |>
pivot_wider(id_cols = Country, values_from = `CFR, %`, names_from = HospitalizedEver)
Otherwise, R would throw the error
df_CFR_hosp |>
pivot_wider(values_from = `CFR, %`, names_from = HospitalizedEver)
## Error in `pivot_wider()`:
## ! Names must be unique.
## ✖ These names are duplicated:
## * "NA" at locations 4 and 9.
## ℹ Use argument `names_repair` to specify repair strategy.
Now, let’s try to work characterizing the CFR by age group. First, we
would need to create those age groups. We do it by using the special
command cut from dplyr package.
df |>
mutate(Age_group = cut(Age,
# break points
breaks=c(seq(0, 80, 5), 120),
# labels, otherwise it would be labeled [0,5), [5, 10), ...
labels=seq(0, 80, 5),
# to include the left bound [5,10)
# instead of the right bound (5, 10]
right = F)) |>
# just rearanging the columns, so you would easily see Age and Age_groups
select(Country, Age, Age_group, everything()) -> df_age_groups
df_age_groups
Here you see that we create breaks with the upper bound 120 (if
someone is older than 120 years, which is impossible, they would be
assigned to NA
c(seq(0, 80, 5), 120)
## [1] 0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 120
While labels are
seq(0, 80, 5)
## [1] 0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80
Finally we check our labels
df_age_groups$Age_group |> unique()
## [1] 45 40 0 30 10 70 5 25 <NA> 50 55 35 20 15 80
## [16] 75 60 65
## Levels: 0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80
Now we calculate similarly (your homework)
df_age_groups |>
pivot_wider(...) # please continue