Code
library(tidyverse)
library(gtsummary)We will be introducing birthwt dataset from the MASS package which was collected at Baystate Medical Center, Springfield, Mass during 1986 on Risk Factors Associated with Low Infant Birth Weight.
The same dataset can be loaded directly from the MASS package. However, for additional learnings, we have provided the dataset in varied formats for the participants to learn data import during the group activities.
We would like to reiterate that creating a project and required folders at the beginning of a research work is a gold standard database management strategy. Go ahead and create your own projects and folders for the activity.
To use functions from varied packages/ libraries other than baseR, we need to explicitly load those libraries. For this session, following libraries will be used:-
The loading of libraries into your current session can be optional. In case you are going to use a function only once from a library, it is computationally better to explicity call the function using ::. Discuss!
rio: A Swiss-Army Knife for Data I/O (Click to learn more)tidyverse: R packages for Data Science (Click to learn more)skimr: For quick summary statistics (Click to learn more)here: A Simpler Way to Find Your Files (Click to learn more)MASS: Functions and datasets to support Venables and Ripley, “Modern Applied Statistics with S” (4th edition, 2002) (Click to learn more)R possesses a simple generic function mechanism which can be used for an object-oriented style of programming (OOP). Method dispatch takes place based on the class of the first argument to the generic function.
When dealing with rectagular spreadsheets, it is a good habit to set the class of the dataset to tibble for a tidy analysis.
import function from the rio package read a data.frame from a file. Exceptions to this rule are Rdata, RDS, and JSON input file formats, which return the originally saved object without changing its class. To set a class, we can use an argument setclass.
glimpse function.glimpse() is like a transposed version of print(): columns run down the page, and data runs across. This makes it possible to see every column in a data frame. It’s a little like str() applied to a data frame but it tries to show you as much data as possible.
Rows: 189
Columns: 10
$ low <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
$ age <dbl> 19, 33, 20, 21, 18, 21, 22, 17, 29, 26, 19, 19, 22, 30, 18, 18, …
$ lwt <dbl> 182, 155, 105, 108, 107, 124, 118, 103, 123, 113, 95, 150, 95, 1…
$ race <dbl> 2, 3, 1, 1, 1, 3, 1, 3, 1, 1, 3, 3, 3, 3, 1, 1, 2, 1, 3, 1, 3, 1…
$ smoke <dbl> 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0…
$ ptl <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0…
$ ht <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0…
$ ui <dbl> 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1…
$ ftv <dbl> 0, 3, 1, 2, 0, 0, 1, 1, 1, 0, 0, 1, 0, 2, 0, 0, 0, 3, 0, 1, 2, 3…
$ bwt <dbl> 2523, 2551, 2557, 2594, 2600, 2622, 2637, 2637, 2663, 2665, 2722…
Understanding the data structure helps you understand the way data cleaning/wrangling and subsequent analysis is required. Here, the birthwt data frame has 189 rows and 10 columns. All the variables are dbl (means double precision, a quantitative variable that is essentially continuous - taking decimal values).
summary functionsummary() is a generic function used to produce result summaries of the results of various model fitting functions. The function invokes particular methods which depend on the class of the first argument.
low age lwt race
Min. :0.0000 Min. :14.00 Min. : 80.0 Min. :1.000
1st Qu.:0.0000 1st Qu.:19.00 1st Qu.:110.0 1st Qu.:1.000
Median :0.0000 Median :23.00 Median :121.0 Median :1.000
Mean :0.3122 Mean :23.24 Mean :129.8 Mean :1.847
3rd Qu.:1.0000 3rd Qu.:26.00 3rd Qu.:140.0 3rd Qu.:3.000
Max. :1.0000 Max. :45.00 Max. :250.0 Max. :3.000
smoke ptl ht ui
Min. :0.0000 Min. :0.0000 Min. :0.00000 Min. :0.0000
1st Qu.:0.0000 1st Qu.:0.0000 1st Qu.:0.00000 1st Qu.:0.0000
Median :0.0000 Median :0.0000 Median :0.00000 Median :0.0000
Mean :0.3915 Mean :0.1958 Mean :0.06349 Mean :0.1481
3rd Qu.:1.0000 3rd Qu.:0.0000 3rd Qu.:0.00000 3rd Qu.:0.0000
Max. :1.0000 Max. :3.0000 Max. :1.00000 Max. :1.0000
ftv bwt
Min. :0.0000 Min. : 709
1st Qu.:0.0000 1st Qu.:2414
Median :0.0000 Median :2977
Mean :0.7937 Mean :2945
3rd Qu.:1.0000 3rd Qu.:3487
Max. :6.0000 Max. :4990
skim function.skim() is an alternative to summary(), quickly providing a broad overview of a data frame. It handles data of all types, dispatching a different set of summary functions based on the types of columns in the data frame.
| Name | df |
| Number of rows | 189 |
| Number of columns | 10 |
| _______________________ | |
| Column type frequency: | |
| numeric | 10 |
| ________________________ | |
| Group variables | None |
Variable type: numeric
| skim_variable | n_missing | complete_rate | mean | sd | p0 | p25 | p50 | p75 | p100 | hist |
|---|---|---|---|---|---|---|---|---|---|---|
| low | 0 | 1 | 0.31 | 0.46 | 0 | 0 | 0 | 1 | 1 | ▇▁▁▁▃ |
| age | 0 | 1 | 23.24 | 5.30 | 14 | 19 | 23 | 26 | 45 | ▇▇▃▁▁ |
| lwt | 0 | 1 | 129.81 | 30.58 | 80 | 110 | 121 | 140 | 250 | ▆▇▂▁▁ |
| race | 0 | 1 | 1.85 | 0.92 | 1 | 1 | 1 | 3 | 3 | ▇▁▂▁▆ |
| smoke | 0 | 1 | 0.39 | 0.49 | 0 | 0 | 0 | 1 | 1 | ▇▁▁▁▅ |
| ptl | 0 | 1 | 0.20 | 0.49 | 0 | 0 | 0 | 0 | 3 | ▇▁▁▁▁ |
| ht | 0 | 1 | 0.06 | 0.24 | 0 | 0 | 0 | 0 | 1 | ▇▁▁▁▁ |
| ui | 0 | 1 | 0.15 | 0.36 | 0 | 0 | 0 | 0 | 1 | ▇▁▁▁▂ |
| ftv | 0 | 1 | 0.79 | 1.06 | 0 | 0 | 0 | 1 | 6 | ▇▂▁▁▁ |
| bwt | 0 | 1 | 2944.59 | 729.21 | 709 | 2414 | 2977 | 3487 | 4990 | ▁▅▇▆▁ |
dplyr is a package grouped inside tidyverse collection of packages. dplyr package is very useful to “munge”, “wrangle”, or “transform” your data. It is a grammar of data manipulation. It provides a consistent set of verbs that help you solve the most common data manipulation challenges.
The common data wrangling functions include:
rename(): To change the names of the variables.select(): To reduce the size of dataset by selecting certain variables (or columns).mutate(): To generate new variable/ transform existing variables.arrange(): To sort observation of a variable.filter(): To group observations based on certain criteria.group_by(): To reduce variables to groups in order to estimate summary statistic.rename() provides several advantages over traditional renaming methods, especially in the context of data manipulation.
rename() is concise and intuitive. You specify the new column name first, making it easier to read and understand.rename() integrates well with the pipe operator (|>), which allows chaining multiple data manipulation steps.rename() allows you to rename only the columns you need without affecting others. This is convenient when working with large datasets.rename() throws an informative error, helping catch typos early. This behavior is safer compared to manually changing column names, where typos might go unnoticed. [1] "child_weight_cat" "maternal_age" "maternal_weight"
[4] "race" "smoke" "number_preterm"
[7] "hypertension" "uterine_irritability" "health_visits"
[10] "birth_weight"
The function factor is used to encode a vector as a factor. The same can be used within the mutate function as an argument for data transformation.
df <- df |>
mutate(smoke_cat = factor(smoke,
levels = c(0,1),
labels = c("Non-smoker",
"Smoker")),
race_cat = factor(race,
levels = c(1,2,3),
labels = c("White",
"Black",
"Other")),
child_weight_cat = factor(child_weight_cat,
levels = c(0,1),
labels = c("Normal", "Low Birth Weight")))
df |>
select(smoke_cat, race_cat, child_weight_cat) |>
summary() smoke_cat race_cat child_weight_cat
Non-smoker:115 White:96 Normal :130
Smoker : 74 Black:26 Low Birth Weight: 59
Other:67
# A tibble: 6 × 12
child_weight_cat maternal_age maternal_weight race smoke number_preterm
<fct> <dbl> <dbl> <dbl> <dbl> <dbl>
1 Normal 14 135 1 0 0
2 Low Birth Weight 14 101 3 1 1
3 Low Birth Weight 14 100 3 0 0
4 Normal 15 98 2 0 0
5 Low Birth Weight 15 110 1 0 0
6 Low Birth Weight 15 115 3 0 0
# ℹ 6 more variables: hypertension <dbl>, uterine_irritability <dbl>,
# health_visits <dbl>, birth_weight <dbl>, smoke_cat <fct>, race_cat <fct>
# A tibble: 6 × 12
child_weight_cat maternal_age maternal_weight race smoke number_preterm
<fct> <dbl> <dbl> <dbl> <dbl> <dbl>
1 Normal 45 123 1 0 0
2 Normal 36 202 1 0 0
3 Normal 36 175 1 0 0
4 Normal 35 121 2 1 1
5 Normal 35 170 1 0 1
6 Low Birth Weight 34 187 2 1 0
# ℹ 6 more variables: hypertension <dbl>, uterine_irritability <dbl>,
# health_visits <dbl>, birth_weight <dbl>, smoke_cat <fct>, race_cat <fct>
# A tibble: 26 × 12
child_weight_cat maternal_age maternal_weight race smoke number_preterm
<fct> <dbl> <dbl> <dbl> <dbl> <dbl>
1 Normal 19 182 2 0 0
2 Normal 15 98 2 0 0
3 Normal 26 168 2 1 0
4 Normal 17 113 2 0 0
5 Normal 17 113 2 0 0
6 Normal 35 121 2 1 1
7 Normal 25 125 2 0 0
8 Normal 21 185 2 1 0
9 Normal 23 130 2 0 0
10 Normal 22 158 2 0 1
# ℹ 16 more rows
# ℹ 6 more variables: hypertension <dbl>, uterine_irritability <dbl>,
# health_visits <dbl>, birth_weight <dbl>, smoke_cat <fct>, race_cat <fct>
Most data operations are done on groups defined by variables. group_by() takes an existing tbl and converts it into a grouped tbl where operations are performed “by group”.
# A tibble: 189 × 12
# Groups: race_cat [3]
child_weight_cat maternal_age maternal_weight race smoke number_preterm
<fct> <dbl> <dbl> <dbl> <dbl> <dbl>
1 Normal 19 182 2 0 0
2 Normal 33 155 3 0 0
3 Normal 20 105 1 1 0
4 Normal 21 108 1 1 0
5 Normal 18 107 1 1 0
6 Normal 21 124 3 0 0
7 Normal 22 118 1 0 0
8 Normal 17 103 3 0 0
9 Normal 29 123 1 1 0
10 Normal 26 113 1 1 0
# ℹ 179 more rows
# ℹ 6 more variables: hypertension <dbl>, uterine_irritability <dbl>,
# health_visits <dbl>, birth_weight <dbl>, smoke_cat <fct>, race_cat <fct>
In this session, we worked on understanding the data structure, variable names, class, and used dplyr verbs for data wrangling. Once the dataset is ready for analysis, we move towards Exploratory Data Analysis. It is an iterative process for a robust analysis later.