[,1] [,2] [,3]
[1,] "a" "c" "e"
[2,] "b" "d" "f"
Part 1: R Basics
Karissa Whiting
June 10th, 2025
Provide you tools & resources to get properly set up to conduct impactful and reproducible research during your time at MSK (and after!)
Beginners: Introduce you to general coding concepts and basics of the R programming language
Intermediate/Advanced Coders: Fill potential gaps in your R knowledge and introduce packages useful for common statistical analyses and reporting.
All: Learn to build reproducible code bases (of any language) from the ground up.
R is an open-source programming language used mostly for statistical computing and graphics. R is an object-oriented language, with a functional style.
Open source means the original source code is freely available, and can be distributed and modified. Also, users can contribute to the usefulness by creating packages, which implement specialized functions for all kinds of uses (e.g. statistical methods, graphical capabilities, reporting tools). Added Bonus: vibrant R community!
RStudio is an integrated development environment (IDE) for R. It includes a console, syntax-highlighting code editor that supports direct code execution, as well as tools for plotting, history, debugging and work space management.
Python is a versatile programming language used widely in data science, web development, automation, and statistics. Unlike R, it was created as a general purpose language but has evolved significantly.
Python is also Open source (PyPI - Python Package Index)
Some popular IDEs include VS Code, JupyterLab, Positron and more
Which is better?
They’re both great!
<- is the assignment operator (= also works)? is your friend if you want to look at documentation! (e.g. type ?mean() in the console)The %>% (pipe) is a useful way to link functions together to make your code more succinct and easier to read.
|> (base pipe) is another way to pipe operations
R basic data types:
TRUE)1)1.2)"Purple")What is the most flexible data type?
Since columns of a data.frame must be of the same type, some data may be coerced in unexpected ways when reading in a csv or excel file.
Character type is often the default for mixed data types
What will happen when we try to add these?
R has 5 basic data structures:
3. array
5. data.frame/tibble
- Any data type is allowed, BUT each column has to have the SAME type
- Most important for data analysts. Most similar to an excel spreadsheet/statistical data file
Steps of a basic data analysis project:
1. Setup Your Project
2. Clean and Explore Data
3. Analyze Data
4. Report Your Findings
5. Iterate, Share, and Collaborate!
1. Setup Your Project
- `here`, `renv`
2. Clean and Explore Data
- `tidyverse`
3. Analyze Data
- `stats`
- `survival`, `lme4`, `glmnet`
- `ggplot2`
4. Report Your Findings
- R Markdown / Quarto
- `gt` / `gtsummary`
5. Iterate, Share, and Collaborate!
- git / GitHub
1. Setup Your Project
- `venv`, `conda`
2. Clean and Explore Data
- `pandas` / `numpy`
3. Analyze Data
- `scipy.stats`, `statsmodels`, `scikit-learn`
- `seaborn`, `matplotlib`
4. Report Your Findings
- Jupyter / Quarto
5. Iterate, Share, and Collaborate!
- git / GitHub
Steps of a basic data analysis project:
1. Setup Your Project
Clean and Explore Data
Analyze Data
Report Your Findings
Iterate, Share, and Collaborate!
keep raw and processed data separate (raw-data, vs. data)
folder for scripts ordered or labelled descriptively
optionally can have admin for project notes, etc and outputs for final reports and figures
README - text file that introduces and explains a project (usethis::use_readme_md())
R Project (.Rproj file) - tells RStudio all your files belong to one project and sets working directory for entire project.
Create a new folder on your computer and name it “your-initials-case-study-2025”
Create subfolders within your project folder called: admin, raw-data, scripts, data, outputs
Create a new R Project in Rstudio from this folder (File > New Project > Existing Directory)
Create a README.md using usethis::use_readme_md()
Open a new R file (RStudio > New File > R Script) to use as a scratch file
Steps of a basic data analysis project:
2. Clean and Explore Data
Analyze Data
Report Your Findings
Iterate, Share, and Collaborate!
colnames() - will give you the column namesncol() and nrow() - will give you the total count of columns and rows respectivelyclass(), str(), attributes() will give you meta-information on the objecthead(), tail() show the top or bottom rows of your dfView() will show the whole dataframetable() will summarise variablesTry these out:
The tidyverse package is a collection of R packages designed for data analysis, all of which share a similar design, grammar, and structure.
There are several additional packages which are installed as part of the tidyverse, but are not loaded by default.
Overall the tidyverse style emphasizes code readability and intuitive coding
Human-readable syntax and pipe-based workflows
Shortcuts for common data manipulation tasks
tidyverse has been developed and significantly improved in the last few years, with a lot of ongoing work being done to further increase usability.
The dplyr package is a data manipulation and cleaning package. A few of the key functions (verbs) in dplyr are:
All take a data frame as input, and return a data frame as output.
Steps of a basic data analysis project:
Setup Your Project
Clean and Explore Data
3. Analyze Data
Report Your Findings
Iterate, Share, and Collaborate!
We will cover:
linear model
logistic model
survival analyses
and more….(depending on what’s useful for you!)
~ is used to separate your outcome on the left hand side and your predictors on the right hand side~chisq.test() do not use the ~ notationstats package is already loaded in R which will make it easier to use common statistical testsmodel(outcome ~ covariates, data)mtcars$vs <- as.character(mtcars$vs)
mtcars$cyl <- as.character(mtcars$cyl)
mod1 <- lm(mpg ~ vs * cyl, data = mtcars)
class(mod1) # class of lm which is a list[1] “lm”
[1] “coefficients” “residuals” “effects” “rank”
[5] “fitted.values” “assign” “qr” “df.residual”
[9] “contrasts” “xlevels” “call” “terms”
[13] “model”
Call:
lm(formula = mpg ~ vs * cyl, data = mtcars)
Residuals:
Min 1Q Median 3Q Max
-5.3300 -1.4437 0.0875 1.5250 7.1700
Coefficients: (1 not defined because of singularities)
Estimate Std. Error t value Pr(>|t|)
(Intercept) 26.000 3.318 7.836 2e-08 ***
vs1 0.730 3.480 0.210 0.83541
cyl6 -5.433 3.831 -1.418 0.16757
cyl8 -10.900 3.434 -3.174 0.00374 **
vs1:cyl6 -2.172 4.305 -0.504 0.61801
vs1:cyl8 NA NA NA NA
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 3.318 on 27 degrees of freedom
Multiple R-squared: 0.7361, Adjusted R-squared: 0.697
F-statistic: 18.82 on 4 and 27 DF, p-value: 1.696e-07
(If the Cook’s Distance of a data point exceeds this cutoff, that data point might be considered unusually influential)
Call:
lm(formula = mpg ~ vs * cyl, data = mtcars)
Residuals:
Min 1Q Median 3Q Max
-5.3300 -1.4437 0.0875 1.5250 7.1700
Coefficients: (1 not defined because of singularities)
Estimate Std. Error t value Pr(>|t|)
(Intercept) 26.000 3.318 7.836 2e-08 ***
vs1 0.730 3.480 0.210 0.83541
cyl6 -5.433 3.831 -1.418 0.16757
cyl8 -10.900 3.434 -3.174 0.00374 **
vs1:cyl6 -2.172 4.305 -0.504 0.61801
vs1:cyl8 NA NA NA NA
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 3.318 on 27 degrees of freedom
Multiple R-squared: 0.7361, Adjusted R-squared: 0.697
F-statistic: 18.82 on 4 and 27 DF, p-value: 1.696e-07
broom and gt/gtsummary will helpbroom is a package that helps tidy model results into data.framesgtmoddf <- broom::tidy(mod1) %>% #didn't load broom just called one function
mutate(p.value = round(p.value,3)) %>%
select(-std.error)
gt::gt(moddf)| term | estimate | statistic | p.value |
|---|---|---|---|
| (Intercept) | 26.000000 | 7.8364568 | 0.000 |
| vs1 | 0.730000 | 0.2097843 | 0.835 |
| cyl6 | -5.433333 | -1.4182193 | 0.168 |
| cyl8 | -10.900000 | -3.1738857 | 0.004 |
| vs1:cyl6 | -2.171667 | -0.5044923 | 0.618 |
| vs1:cyl8 | NA | NA | NA |
| Characteristic | Beta | 95% CI1 | p-value |
|---|---|---|---|
| vs | |||
| 0 | — | — | |
| 1 | 0.73 | -6.4, 7.9 | 0.8 |
| cyl | |||
| 4 | — | — | |
| 6 | -5.4 | -13, 2.4 | 0.2 |
| 8 | -11 | -18, -3.9 | 0.004 |
| vs * cyl | |||
| 1 * 6 | -2.2 | -11, 6.7 | 0.6 |
| 1 * 8 | |||
| 1 CI = Confidence Interval | |||
There are tons of ways to customize your basic {gtsummary} outputs.
Example of adding labels:
| Characteristic | Beta | 95% CI1 | p-value |
|---|---|---|---|
| vs | |||
| 0 | — | — | |
| 1 | 0.73 | -6.4, 7.9 | 0.8 |
| Cylinder | |||
| 4 | — | — | |
| 6 | -5.4 | -13, 2.4 | 0.2 |
| 8 | -11 | -18, -3.9 | 0.004 |
| vs * Cylinder | |||
| 1 * 6 | -2.2 | -11, 6.7 | 0.6 |
| 1 * 8 | |||
| 1 CI = Confidence Interval | |||
| Characteristic | OR1 | 95% CI1 | p-value |
|---|---|---|---|
| am | |||
| 0 | — | — | |
| 1 | 2.00 | 0.48, 8.76 | 0.3 |
| 1 OR = Odds Ratio, CI = Confidence Interval | |||
| Characteristic | HR1 | 95% CI1 | p-value |
|---|---|---|---|
| ph.ecog | |||
| 0 | — | — | |
| 1 | 1.52 | 1.03, 2.25 | 0.036 |
| 2 | 2.58 | 1.66, 4.01 | <0.001 |
| 3 | 7.76 | 1.04, 58.0 | 0.046 |
| sex | |||
| 1 | — | — | |
| 2 | 0.58 | 0.42, 0.81 | 0.001 |
| 1 HR = Hazard Ratio, CI = Confidence Interval | |||
Cox models assume proportional hazards
Test this assumptions: