The first step is the setup chunk, to configure the global options of your Rmarkdown document. Here we will chose to display the code in the ouput unless sepcified otherwise.
# The next function specify that every chunk will have the echo parameter to TRUE and the code will be displayed in the html
knitr::opts_chunk$set(echo = TRUE)
options(knitr.duplicate.label = "allow")
Note : chunks are named (either
explicity or with a number). This is useful for debugging (as the error
message will indicate which chunk is problematic). But Rmarkdown doesn’t
allow to have several chunks with the same name. In the setup chunk you
can specify options(knitr.duplicate.label = "allow") to
allow this.
You could have specified
{r setup, include = FALSE, message = FALSE} to remove the
chunk from the rendering and to ignore all messages. (This is often done
for the setup chunk.)
The second step is to load the libraries you will use throughout the R Markdown report.
When writing an R Markdown document, you may use different packages
at different stages.
A good practice is to load all of them at the beginning of the
report.
library(tidyverse)
# You may install the DT package if not in your library
# install.packages("DT")
# You shouldn't install packages directly in an R Markdown report, as it may cause errors when knitting the document. Instead, install the packages in your R console, and simply add a comment in your report to indicate which packages need to be installed.
library(DT)
In the library chunk, you can specify message = FALSE to
suppress messages, as library messages often include advice on how to
cite the package in publications or describe the package’s purpose.
The new step is to import your data. In this
example, my data are located in the folder Data.
You should adjust the file path according to the location of your data to ensure the report can be knitted successfully.
Cancer_Data = read.csv("../Data/cancer_data/Cancer_Data.csv", stringsAsFactors = TRUE, row.names = 1)
Make sure that every object called in a Rmd has been created beforehand in the same Rmd.
In order to use the dataset for plotting, you first need to
inspect it and remove any missing values. To perform
this, you can use the function summary().
summary(Cancer_Data)
## ID diagnosis radius texture
## Min. : 8670 B :339 Min. : 6.981 Min. : 9.71
## 1st Qu.: 869218 M :203 1st Qu.:11.700 1st Qu.:16.21
## Median : 906024 NA's: 27 Median :13.370 Median :18.88
## Mean : 30371831 Mean :14.127 Mean :19.35
## 3rd Qu.: 8813129 3rd Qu.:15.780 3rd Qu.:21.80
## Max. :911320502 Max. :28.110 Max. :39.28
## NA's :33
## perimeter smoothness concavity concave.points
## Min. : 43.79 Min. :0.05263 Min. :0.00000 Min. :0.00000
## 1st Qu.: 75.17 1st Qu.:0.08637 1st Qu.:0.02956 1st Qu.:0.02033
## Median : 86.24 Median :0.09587 Median :0.06154 Median :0.03350
## Mean : 91.97 Mean :0.09636 Mean :0.08880 Mean :0.04912
## 3rd Qu.:104.10 3rd Qu.:0.10530 3rd Qu.:0.13070 3rd Qu.:0.07409
## Max. :188.50 Max. :0.16340 Max. :0.42680 Max. :0.20120
## NA's :22
You can observe several missing values, which we will remove using
na.omit().
We will also create a smaller dataset containing only the relevant columns, which will be easier to work with. Specifically, we will use the solution from Question 3 of TP6 to generate a reduced dataset and then perform some basic analysis.
This new dataset, called Cancer_Data_subset,
will exclude missing values and include only the columns we are
interested in.
Creating a copy of the dataset allows us to retain the
original Cancer_Data in case we need to use it
later.
Cancer_Data_subset = Cancer_Data %>%
na.omit() %>%
dplyr::select(
diagnosis,
radius,
texture,
perimeter,
smoothness,
concavity
)
Note : We used explicit function calls here to avoid potential issues. In fact, it is considered good practice to always call functions this way to prevent accidentally using a function from another package without realizing it.
Warning : In the previous code, you can
see that filtering with na.omit() is performed before
selecting columns. If the order was different, the number of rows might
change. It’s up to you whether to apply filtering to the full dataset or
only to a subset of selected columns, but be aware that this choice can
lead to different results.
We can inspect the data again to visualize if there are missing values left.
summary(Cancer_Data_subset)
## diagnosis radius texture perimeter smoothness
## B:310 Min. : 6.981 Min. : 9.71 Min. : 43.79 Min. :0.06251
## M:182 1st Qu.:11.688 1st Qu.:16.33 1st Qu.: 75.14 1st Qu.:0.08587
## Median :13.335 Median :18.82 Median : 86.14 Median :0.09589
## Mean :14.082 Mean :19.35 Mean : 91.67 Mean :0.09648
## 3rd Qu.:15.750 3rd Qu.:21.79 3rd Qu.:103.62 3rd Qu.:0.10540
## Max. :28.110 Max. :39.28 Max. :188.50 Max. :0.16340
## concavity
## Min. :0.00000
## 1st Qu.:0.02964
## Median :0.05994
## Mean :0.08704
## 3rd Qu.:0.12662
## Max. :0.42680
We can see the head of the dataset below.
# Using the head() function on our data :
head(Cancer_Data_subset)
## diagnosis radius texture perimeter smoothness concavity
## 842302 M 17.99 10.38 122.80 0.11840 0.3001
## 842517 M 20.57 17.77 132.90 0.08474 0.0869
## 84348301 M 11.42 20.38 77.58 0.14250 0.2414
## 84358402 M 20.29 14.34 135.10 0.10030 0.1980
## 843786 M 12.45 15.70 82.57 0.12780 0.1578
## 844359 M 18.25 19.98 119.60 0.09463 0.1127
# Or we could have used dplyr with
# Cancer_Data_subset %>%
# head()
We can display it more properly with knitr::kable().
knitr::kable(head(Cancer_Data_subset))
| diagnosis | radius | texture | perimeter | smoothness | concavity | |
|---|---|---|---|---|---|---|
| 842302 | M | 17.99 | 10.38 | 122.80 | 0.11840 | 0.3001 |
| 842517 | M | 20.57 | 17.77 | 132.90 | 0.08474 | 0.0869 |
| 84348301 | M | 11.42 | 20.38 | 77.58 | 0.14250 | 0.2414 |
| 84358402 | M | 20.29 | 14.34 | 135.10 | 0.10030 | 0.1980 |
| 843786 | M | 12.45 | 15.70 | 82.57 | 0.12780 | 0.1578 |
| 844359 | M | 18.25 | 19.98 | 119.60 | 0.09463 | 0.1127 |
Here we use the function datatable from the
DT package to show the table. Using this function allows
many things, notably to sort and filter the table directly on the html
report (sort by clicking on a column name and filter with the search
cell of the html). This is not possible with some other basic functions
(knitr::kable for example).
# The option `scrollX=TRUE` mean you can scroll in the x axis, if the table is too wide.
DT::datatable(data = Cancer_Data_subset,
rownames = TRUE, # This displays the rownames of our data
options = list( # datatable function has many other options as well
scrollX = TRUE, # This enables to scroll horizontally if there is too many columns
pageLength=5 # This controls the number of lines displayed
))
Now we will use the package ggplot2 in order to make
plots. We will recreate the plots from TP6.
The first step was to create an histogram showing the distribution of the radius of the tumors.
You can use ggplot:Esquisse to have the main code. But
Esquisse has its limits and you can’t add vertical
lines for example. To do it, you can copy and paste the code from
Esquisse then add + geom_vline() to add this vertical
line.
Note that you can’t use Esquisse when generating a
Rmarkdown report. If you want to use it, you necessarily
have to retrieve the code from Esquisse and copy it in a
chunk, and then render your document.
ggplot(Cancer_Data_subset) +
aes(x = radius) +
geom_histogram(bins = 30L, fill = "#91ABDA") +
theme_minimal() +
geom_vline(xintercept = mean(Cancer_Data_subset$radius),
colour = "red")
You can also create a boxplot showing the radius depending of the type diagnosis of the tumors.
ggplot(Cancer_Data_subset) +
aes(x = diagnosis, y = radius, fill = diagnosis) +
geom_boxplot() +
scale_fill_viridis_d(option = "viridis", direction = 1) +
labs(
x = "Diagnosis",
y = "Radius",
title = "Radius by diagnosis",
fill = "Diagnosis"
) +
theme_minimal() +
theme(legend.position = "none") # This argument is used to remove the legend
Here we display the scatterplot of the perimeter according to concavity colored by diagnosis.
ggplot(Cancer_Data_subset) +
aes(x = perimeter, y = concavity, colour = diagnosis) +
geom_point(size = 2.3, shape = "triangle") +
scale_color_manual(
values = c(
B = "#6D7BF8",
M = "#E85C3C"
)
) +
labs(x = "Perimeter",
y = "Concavity",
title = "Perimeter according to Concavity, colored by diagnosis",
fill = "Region") +
theme_minimal()
## Ignoring unknown labels:
## • fill : "Region"
It is useful to show the session info at the end of the report to indicate which packages have been used and their versions.
sessionInfo()
## R version 4.4.2 (2024-10-31)
## Platform: x86_64-pc-linux-gnu
## Running under: Ubuntu 24.04.1 LTS
##
## Matrix products: default
## BLAS: /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.12.0
## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.12.0
##
## locale:
## [1] LC_CTYPE=fr_FR.UTF-8 LC_NUMERIC=C
## [3] LC_TIME=fr_FR.UTF-8 LC_COLLATE=fr_FR.UTF-8
## [5] LC_MONETARY=fr_FR.UTF-8 LC_MESSAGES=fr_FR.UTF-8
## [7] LC_PAPER=fr_FR.UTF-8 LC_NAME=C
## [9] LC_ADDRESS=C LC_TELEPHONE=C
## [11] LC_MEASUREMENT=fr_FR.UTF-8 LC_IDENTIFICATION=C
##
## time zone: Europe/Paris
## tzcode source: system (glibc)
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] DT_0.34.0 lubridate_1.9.4 forcats_1.0.1 stringr_1.6.0
## [5] dplyr_1.1.4 purrr_1.2.1 readr_2.1.6 tidyr_1.3.2
## [9] tibble_3.3.1 ggplot2_4.0.1 tidyverse_2.0.0
##
## loaded via a namespace (and not attached):
## [1] gtable_0.3.6 jsonlite_2.0.0 compiler_4.4.2 tidyselect_1.2.1
## [5] dichromat_2.0-0.1 jquerylib_0.1.4 scales_1.4.0 yaml_2.3.12
## [9] fastmap_1.2.0 R6_2.6.1 labeling_0.4.3 generics_0.1.4
## [13] knitr_1.51 htmlwidgets_1.6.4 tzdb_0.5.0 bslib_0.9.0
## [17] pillar_1.11.1 RColorBrewer_1.1-3 rlang_1.1.7 stringi_1.8.7
## [21] cachem_1.1.0 xfun_0.55 sass_0.4.10 S7_0.2.1
## [25] otel_0.2.0 viridisLite_0.4.2 timechange_0.3.0 cli_3.6.5
## [29] withr_3.0.2 magrittr_2.0.4 crosstalk_1.2.2 digest_0.6.39
## [33] grid_4.4.2 rstudioapi_0.17.1 hms_1.1.4 lifecycle_1.0.5
## [37] vctrs_0.6.5 evaluate_1.0.5 glue_1.8.0 farver_2.1.2
## [41] rmarkdown_2.30 tools_4.4.2 pkgconfig_2.0.3 htmltools_0.5.9