| Title: | Scientific Calculations for Quantitative Clinical Pharmacology and Pharmacometrics Analysis |
|---|---|
| Description: | Utility functions helpful for reproducible scientific calculations. |
| Authors: | Matthew Smith [aut, cre], Jacob Dumbleton [aut], Jenna Johnson [aut], Devin Pastoor [aut], Wesley Cummings [ctb], Emily Schapiro [ctb], Ryan Crass [ctb], Jonah Lyon [ctb], Elizabeth LeBeau [ctb] |
| Maintainer: | Matthew Smith <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.4.2 |
| Built: | 2026-09-18 16:56:00 UTC |
| Source: | https://github.com/a2-ai/scicalc |
Converts relative eGFR (normalized to 1.73 m²) to absolute eGFR using the patient's actual body surface area.
aegfr(egfr, bsa)aegfr(egfr, bsa)
egfr |
estimated glomerular filtration rate (mL/min/1.73 m²) |
bsa |
body surface area (m²) |
Absolute eGFR is calculated as:
where:
= relative eGFR (mL/min/1.73m²)
= body surface area (m²)
Absolute eGFR (mL/min)
Other renal_function:
crcl(),
egfr(),
rfc()
aegfr(90, 1.9) df <- data.frame( ID = c(1, 2, 3, 4), EGFR = c(80, 95, 70, 60), BSA = c(1.60, 1.85, 1.75, 2.00) ) df <- df |> dplyr::group_by(ID) |> dplyr::mutate(AEGFR = aegfr(EGFR, BSA)) dfaegfr(90, 1.9) df <- data.frame( ID = c(1, 2, 3, 4), EGFR = c(80, 95, 70, 60), BSA = c(1.60, 1.85, 1.75, 2.00) ) df <- df |> dplyr::group_by(ID) |> dplyr::mutate(AEGFR = aegfr(EGFR, BSA)) df
Categorizes subjects into FDA-defined age groups for pediatric and geriatric drug development studies.
agec(age)agec(age)
age |
Numeric vector of baseline age in years |
FDA age categories:
1: Neonate: 0 to <28 days
2: Infant: 28 days to <2 years
3: Child: 2 to <12 years
4: Adolescent: 12 to <18 years
5: Adult: 18 to <65 years
6: Elderly Adult: ≥65 years
Integer vector of age categories (1-6). Returns the value of
getOption("scicalc.missing_value") (default -999) for
missing values. Includes a category_standard attribute set to "FDA".
Set options(scicalc.agec_config = ) to a data frame of custom bands
with columns label, min (lower bound), and code to
replace the FDA bands entirely. Bands are half-open [min, next min)
with the top band open-ended; ages below the lowest min return the
missing value. The category_standard attribute is then "custom". For
example, data.frame(label = c("child", "adult", "senior"),
min = c(0, 18, 65), code = c(1, 2, 3)).
Pediatric Drug Development: Regulatory Considerations — Complying With the Pediatric Research Equity Act and Qualifying for Pediatric Exclusivity Under the Best Pharmaceuticals for Children Act Guidance for Industry
Guideline for Industry Studies in Support of Special Populations: Geriatrics
age_cat <- agec(24) df <- data.frame( ID = 1:12, AGE = c(0.07, 28 / 365, 0.25, 1, 2, 4, 12, 16, 18, 24, 65, 70) ) dplyr::mutate(df, AGEC = agec(AGE))age_cat <- agec(24) df <- data.frame( ID = 1:12, AGE = c(0.07, 28 / 365, 0.25, 1, 2, 4, 12, 16, 18, 24, 65, 70) ) dplyr::mutate(df, AGEC = agec(AGE))
Calculates adjusted ideal body weight, which accounts for excess body weight in obese patients.
aibw( weight, height, sexf, age, allow_ibw_lt_intercept = TRUE, allow_tbw_lt_ibw = TRUE )aibw( weight, height, sexf, age, allow_ibw_lt_intercept = TRUE, allow_tbw_lt_ibw = TRUE )
weight |
baseline weight of subject in kilograms |
height |
baseline height of subject in centimeters |
sexf |
0 = male, 1 = female, from sexf() |
age |
Numeric vector of baseline age in years. |
allow_ibw_lt_intercept |
logical indicating whether to allow ideal body weight to be lower than intercepts (default TRUE). |
allow_tbw_lt_ibw |
logical indicating whether to allow adjusted ideal body weight to be less than IBW (default TRUE). |
Adjusted ideal body weight is calculated as:
where:
= ideal body weight (kg)
= total (actual) body weight (kg)
adjusted ideal body weight (kg)
Other body_composition:
bmi(),
bmic(),
bsa(),
ibw()
df <- data.frame( ID = 1:6, HEIGHT = c(160, 170, 175, 165, 180, 150), WEIGHT = c(53, 71, 78, 55, 72, 43), SEX = c(1, 0, 0, 1, 0, 1), AGE = c(18, 27, 34, 33, 29, 30) ) df <- dplyr::mutate(df, AIBW = aibw(WEIGHT, HEIGHT, SEX, AGE)) dfdf <- data.frame( ID = 1:6, HEIGHT = c(160, 170, 175, 165, 180, 150), WEIGHT = c(53, 71, 78, 55, 72, 43), SEX = c(1, 0, 0, 1, 0, 1), AGE = c(18, 27, 34, 33, 29, 30) ) df <- dplyr::mutate(df, AIBW = aibw(WEIGHT, HEIGHT, SEX, AGE)) df
Calculate Body Mass Index
bmi(weight, height)bmi(weight, height)
weight |
weight of subject (kg) |
height |
height of subject (cm) |
BMI is calculated using the formula:
where:
= weight (kg)
= height (cm)
the BMI value (kg/m^2)
Other body_composition:
aibw(),
bmic(),
bsa(),
ibw()
b <- bmi(80.56, 167) df <- data.frame( "WT" = c(80.56, 71.53, 81.04, 70.17), "HT" = c(167, 161, 163, 164) ) df <- dplyr::mutate(df, bmi = bmi(WT, HT)) dfb <- bmi(80.56, 167) df <- data.frame( "WT" = c(80.56, 71.53, 81.04, 70.17), "HT" = c(167, 161, 163, 164) ) df <- dplyr::mutate(df, bmi = bmi(WT, HT)) df
Categorizes individuals based on their Body Mass Index (BMI) according to standard WHO obesity classification criteria. Validates age to ensure appropriate application of adult BMI categories.
bmic(bmi, age)bmic(bmi, age)
bmi |
Numeric vector of baseline Body Mass Index values (kg/m²) |
age |
Numeric vector of baseline age in years. the function will issue warnings for individuals under 18 years old, as adult BMI categories may not be appropriate for pediatric populations |
BMI Categories:
1: Underweight: BMI < 18.5 kg/m²
2: Normal weight: BMI 18.5 to < 25 kg/m²
3: Overweight: BMI 25 to < 30 kg/m²
4: Obese class 1: BMI 30 to < 35 kg/m²
5: Obese class 2: BMI 35 to < 40 kg/m²
6: Obese class 3: BMI >= 40 kg/m²
Age Considerations: The function will warn if any individuals are under 18 years old, as standard adult BMI categories may not be appropriate for children and adolescents.
Integer vector of obesity categories (1-6). Returns the value of
getOption("scicalc.missing_value") (default -999) for
missing BMI values.
Set options(scicalc.bmic_config = ) to a data frame of custom bands
with columns label, min (lower bound), and code to
replace the WHO bands entirely. Bands are half-open [min, next min)
with the top band open-ended; BMI values below the lowest min return
the missing value. The category_standard attribute is then "custom".
World Health Organization. https://www.who.int/news-room/fact-sheets/detail/obesity-and-overweight
bmi for calculating BMI from weight and height,
agec for age categorization
Other body_composition:
aibw(),
bmi(),
bsa(),
ibw()
patients <- data.frame( ID = 1:6, AGE = c(25, 45, 17, 55, 30, 65), WEIGHT = c(60, 80, 70, 90, 75, 85), HEIGHT = c(165, 175, 170, 180, 160, 175) ) dplyr::mutate( patients, BMI = bmi(WEIGHT, HEIGHT), BMIC = bmic(BMI, AGE) )patients <- data.frame( ID = 1:6, AGE = c(25, 45, 17, 55, 30, 65), WEIGHT = c(60, 80, 70, 90, 75, 85), HEIGHT = c(165, 175, 170, 180, 160, 175) ) dplyr::mutate( patients, BMI = bmi(WEIGHT, HEIGHT), BMIC = bmic(BMI, AGE) )
Calculate Body Surface Area
bsa(weight, height, method = "Dubois")bsa(weight, height, method = "Dubois")
weight |
weight of a subject (kg) |
height |
height of a subject (cm) |
method |
equation to use: bsa(method = "Dubois") or bsa(method = "Mosteller"). |
bsa (m^2)
The method implementations: bsa(method = "Dubois"), bsa(method = "Mosteller").
Other body_composition:
aibw(),
bmi(),
bmic(),
ibw()
bsa(70, 170) bsa(70, 170, method = "Mosteller") bsa(70, 170, method = "Dubois")bsa(70, 170) bsa(70, 170, method = "Mosteller") bsa(70, 170, method = "Dubois")
Categorize Continuous Variable into Quantile Bins
categorize(continuous_var, nbins = 4, units = "", type = 7, digits = 1)categorize(continuous_var, nbins = 4, units = "", type = 7, digits = 1)
continuous_var |
continuous variable data |
nbins |
number of bins to break data into, default is 4 |
units |
string, optional units string to add to labels of categorized data |
type |
type argument for stats::quantile, default is 7 |
digits |
number of digits to round quantile breaks to for labels, default is 1 |
a vector of categorized data as factor
x <- rnorm(1000, mean = 10, sd = 5) categorize(x, nbins = 5)x <- rnorm(1000, mean = 10, sd = 5) categorize(x, nbins = 5)
Check for Unique Units per Parameter
check_for_unique_units(params, units)check_for_unique_units(params, units)
params |
a column from a dataset with lab parameters |
units |
a column from a dataset with units associated with those parameters |
a boolean
Other unit_checking:
get_unique_units_df()
df <- data.frame( PARAM = c( "ALB","ALT","AST","CR","TBIL", "ALB","CR","TBIL","ALT","AST"), UNIT = c( "g/L","U/L","U/L","umol/L","umol/L", "U/L","μmol/L","μmol/L","IU/L","IU/L") ) check_for_unique_units(df$PARAM, df$UNIT)df <- data.frame( PARAM = c( "ALB","ALT","AST","CR","TBIL", "ALB","CR","TBIL","ALT","AST"), UNIT = c( "g/L","U/L","U/L","umol/L","umol/L", "U/L","μmol/L","μmol/L","IU/L","IU/L") ) check_for_unique_units(df$PARAM, df$UNIT)
Convert Albumin Concentration Units
convert_alb(alb)convert_alb(alb)
alb |
albumin concentration (g/L) |
Albumin concentration (g/dL)
Other unit_conversion:
convert_bili(),
convert_creat()
convert_alb(40) df <- data.frame( ID = c(1, 2, 3, 4), ALB = c(35, 40, 28, 45) ) df <- df |> dplyr::group_by(ID) |> dplyr::mutate(ALBBL = convert_alb(ALB)) dfconvert_alb(40) df <- data.frame( ID = c(1, 2, 3, 4), ALB = c(35, 40, 28, 45) ) df <- df |> dplyr::group_by(ID) |> dplyr::mutate(ALBBL = convert_alb(ALB)) df
Convert Bilirubin Concentration Units
convert_bili(bili)convert_bili(bili)
bili |
bilirubin concentration (µmol/L) |
Bilirubin concentration (mg/dL)
Other unit_conversion:
convert_alb(),
convert_creat()
convert_bili(17.1) # ≈ 1 mg/dL df <- data.frame( ID = c(1, 2, 3, 4), BILI = c(10, 15, 25, 40) ) df <- df |> dplyr::group_by(ID) |> dplyr::mutate(BILIBL = convert_bili(BILI)) dfconvert_bili(17.1) # ≈ 1 mg/dL df <- data.frame( ID = c(1, 2, 3, 4), BILI = c(10, 15, 25, 40) ) df <- df |> dplyr::group_by(ID) |> dplyr::mutate(BILIBL = convert_bili(BILI)) df
Convert Serum Creatinine Concentration Units
convert_creat(creat)convert_creat(creat)
creat |
serum creatinine concentration (µmol/L) |
Serum Creatinine concentration (mg/dL)
Other unit_conversion:
convert_alb(),
convert_bili()
convert_creat(88.42) # ≈ 1 mg/dL df <- data.frame( ID = c(1, 2, 3, 4), CREAT = c(70, 90, 110, 130) ) df <- df |> dplyr::group_by(ID) |> dplyr::mutate(CREATBL = convert_creat(CREAT)) dfconvert_creat(88.42) # ≈ 1 mg/dL df <- data.frame( ID = c(1, 2, 3, 4), CREAT = c(70, 90, 110, 130) ) df <- df |> dplyr::group_by(ID) |> dplyr::mutate(CREATBL = convert_creat(CREAT)) df
Computes pairwise correlations between numeric columns and returns results in a tidy long format, sorted by absolute correlation.
cor_df(data, columns = NULL, use = "complete.obs", method = "pearson")cor_df(data, columns = NULL, use = "complete.obs", method = "pearson")
data |
A data.frame containing the variables to correlate |
columns |
Character vector of column names to include. If NULL, all numeric columns will be used. |
use |
Method for handling missing values, passed to cor(). Default is "complete.obs". |
method |
Correlation method, passed to cor(). Default is "pearson". |
A tibble with columns:
Variable pair names (lexicographically ordered)
Correlation coefficient
Absolute correlation coefficient
Results are sorted by ABSCORR in descending order.
Other statistics:
cv(),
geom_cv(),
geom_mean(),
geom_sd()
# Create sample data set.seed(123) df <- data.frame( A = rnorm(100, 5, 2), B = rnorm(100, 10, 3), C = rnorm(100, 15, 1), D = letters[1:100] # non-numeric ) df$B <- df$A * 0.8 + rnorm(100, 0, 1) # Create some correlation # All numeric columns cor_df(df) # Specific columns cor_df(df, columns = c("A", "B", "C"))# Create sample data set.seed(123) df <- data.frame( A = rnorm(100, 5, 2), B = rnorm(100, 10, 3), C = rnorm(100, 15, 1), D = letters[1:100] # non-numeric ) df$B <- df$A * 0.8 + rnorm(100, 0, 1) # Create some correlation # All numeric columns cor_df(df) # Specific columns cor_df(df, columns = c("A", "B", "C"))
Calculate Creatinine Clearance Using Cockcroft-Gault Equation
crcl(sexf, age, creat, weight)crcl(sexf, age, creat, weight)
sexf |
bool of sex of subject. Female: True, Male: False |
age |
age of subject (years) |
creat |
serum creatinine levels (mg/dL) |
weight |
weight of subject (kg) |
The Cockcroft-Gault equation:
where:
= age (years)
= weight (kg)
= serum creatinine (mg/dL)
= 0.85 (female) or 1 (male)
CrCl (mL/min)
Other renal_function:
aegfr(),
egfr(),
rfc()
crcl(FALSE, 20, 10, 70) df <- data.frame( "ID" = c(1, 1, 1, 1, 2, 2, 2, 2), "SEX" = c("F", "F", "F", "F", "M", "M", "M", "M"), "RACE" = c("WHITE", "WHITE", "WHITE", "WHITE", "BLACK", "BLACK", "BLACK", "BLACK"), "AGE" = c(24, 24, 24, 24, 22, 22, 22, 22), "CREAT" = c(1, 1, 1, 1, 4, 4, 4, 4), "WEIGHT" = c(70, 70, 70, 70, 65, 65, 65, 65) ) df <- df |> dplyr::group_by(ID) |> dplyr::mutate(CRCL = crcl(is_female(SEX), AGE, CREAT, WEIGHT)) dfcrcl(FALSE, 20, 10, 70) df <- data.frame( "ID" = c(1, 1, 1, 1, 2, 2, 2, 2), "SEX" = c("F", "F", "F", "F", "M", "M", "M", "M"), "RACE" = c("WHITE", "WHITE", "WHITE", "WHITE", "BLACK", "BLACK", "BLACK", "BLACK"), "AGE" = c(24, 24, 24, 24, 22, 22, 22, 22), "CREAT" = c(1, 1, 1, 1, 4, 4, 4, 4), "WEIGHT" = c(70, 70, 70, 70, 65, 65, 65, 65) ) df <- df |> dplyr::group_by(ID) |> dplyr::mutate(CRCL = crcl(is_female(SEX), AGE, CREAT, WEIGHT)) df
Calculate Coefficient of Variation
cv(x, na.rm = FALSE)cv(x, na.rm = FALSE)
x |
Input vector to compute CV for. |
na.rm |
boolean to remove NA. default is FALSE |
The coefficient of variation is calculated as:
where:
= standard deviation
= mean
CV of x. Standard deviation divided by mean. If you want % you'll need to multiply by 100
Other statistics:
cor_df(),
geom_cv(),
geom_mean(),
geom_sd()
cv(c(1, 2, 1, 1, 2, 1, 2, 3))cv(c(1, 2, 1, 1, 2, 1, 2, 3))
Calculate Estimated Glomerular Filtration Rate
egfr( sexf, raceb, age, creat, ..., cystc = NULL, height = NULL, method = "CKDEPI 2021" )egfr( sexf, raceb, age, creat, ..., cystc = NULL, height = NULL, method = "CKDEPI 2021" )
sexf |
a boolean representing if the patient is female. |
raceb |
a boolean representing if the patient is black. |
age |
the age of a patient in years. |
creat |
the serum creatinine levels in mg/dL. |
... |
reserved; must be empty. Arguments after |
cystc |
the cystatin C levels in mg/L - required for the "CKDEPI 2021 cystatin" method. |
height |
the height of a patient in cm - required for the "Schwartz" method. |
method |
equation to use, one of: egfr(method = "CKDEPI 2009"), egfr(method = "MDRD"), egfr(method = "CKDEPI 2021"), egfr(method = "CKDEPI 2021 cystatin"), egfr(method = "Schwartz"). |
the eGFR calculated based on method.
The method implementations: egfr(method = "CKDEPI 2009"), egfr(method = "MDRD"), egfr(method = "CKDEPI 2021"), egfr(method = "CKDEPI 2021 cystatin"), egfr(method = "Schwartz").
Other renal_function:
aegfr(),
crcl(),
rfc()
e <- egfr(TRUE, TRUE, 24, 1, method = "CKDEPI 2009") df <- data.frame( "SEXF" = c(TRUE, FALSE, TRUE, FALSE), "RACEB" = c(FALSE, FALSE, TRUE, FALSE), "AGE" = c(24, 24, 23, 24), "CREAT" = c(1, 1, 2, 1) ) df <- dplyr::mutate(df, egfr = egfr(SEXF, RACEB, AGE, CREAT, method = "CKDEPI 2009")) dfe <- egfr(TRUE, TRUE, 24, 1, method = "CKDEPI 2009") df <- data.frame( "SEXF" = c(TRUE, FALSE, TRUE, FALSE), "RACEB" = c(FALSE, FALSE, TRUE, FALSE), "AGE" = c(24, 24, 23, 24), "CREAT" = c(1, 1, 2, 1) ) df <- dplyr::mutate(df, egfr = egfr(SEXF, RACEB, AGE, CREAT, method = "CKDEPI 2009")) df
Convert Ethnicity to Numeric Code
ethnicn(ethnicc)ethnicn(ethnicc)
ethnicc |
Ethnic character |
the standard yspec numeric value for the inputted Ethnic character
Other demographics:
is_american_native(),
is_asian(),
is_black(),
is_female(),
is_hispanic_or_latino(),
is_not_hispanic_or_latino(),
is_other(),
is_pacific_islander(),
is_unspecified(),
is_white(),
racen(),
sexf()
ethnicn("HISPANIC OR LATINO") # 1 ethnicn("NOT HISPANIC OR LATINO") # 0 ethnicn("UNKNOWN") # default missing valueethnicn("HISPANIC OR LATINO") # 1 ethnicn("NOT HISPANIC OR LATINO") # 0 ethnicn("UNKNOWN") # default missing value
Calculate Geometric Coefficient of Variation
geom_cv(x, na.rm = FALSE)geom_cv(x, na.rm = FALSE)
x |
vector of data you want the geometric CV of. |
na.rm |
boolean to remove NA from vector. Default is FALSE |
The geometric coefficient of variation is calculated as:
the geometric CV of the input vector x
Other statistics:
cor_df(),
cv(),
geom_mean(),
geom_sd()
geom_cv(c(1, 2, 3, 2, 1))geom_cv(c(1, 2, 3, 2, 1))
Calculate Geometric Mean
geom_mean(x, na.rm = FALSE)geom_mean(x, na.rm = FALSE)
x |
vector to compute geometric mean of |
na.rm |
boolean to remove NA from vector in calcualtion. Default is False |
The geometric mean is calculated as:
geometric mean of input vector x
Other statistics:
cor_df(),
cv(),
geom_cv(),
geom_sd()
geom_mean(c(1, 2, 3, 2, 1))geom_mean(c(1, 2, 3, 2, 1))
Calculate Geometric Standard Deviation
geom_sd(x, na.rm = FALSE)geom_sd(x, na.rm = FALSE)
x |
The vector of data you want the geometric sd of. |
na.rm |
a boolean to remove NA values. Default is False |
The geometric standard deviation is calculated as:
the geometric standard deviation of x
Other statistics:
cor_df(),
cv(),
geom_cv(),
geom_mean()
geom_sd(c(1, 2, 3, 2, 1))geom_sd(c(1, 2, 3, 2, 1))
Get Unique Parameter-Unit Combinations
get_unique_units_df(params, units)get_unique_units_df(params, units)
params |
a column from a dataset with lab parameters |
units |
a column from a dataset with units associated with those parameters |
a dataframe with distinct units and parameters with IU replaced to U and mu replaced with u
Other unit_checking:
check_for_unique_units()
df <- data.frame( PARAM = c( "ALB","ALT","AST","CR","TBIL", "ALB","CR","TBIL","ALT","AST"), UNIT = c( "g/L","U/L","U/L","umol/L","umol/L", "U/L","μmol/L","μmol/L","IU/L","IU/L") ) get_unique_units_df(df$PARAM, df$UNIT)df <- data.frame( PARAM = c( "ALB","ALT","AST","CR","TBIL", "ALB","CR","TBIL","ALT","AST"), UNIT = c( "g/L","U/L","U/L","umol/L","umol/L", "U/L","μmol/L","μmol/L","IU/L","IU/L") ) get_unique_units_df(df$PARAM, df$UNIT)
This function categorizes hepatic function impairment using the National Cancer Institute Organ Dysfunction Working Group (NCI-ODWG) criteria. It evaluates aspartate aminotransferase (AST) and bilirubin levels relative to their upper limits of normal to determine hepatic impairment severity. The function handles edge cases where bilirubin values are very close to category boundaries using floating-point tolerant comparisons.
hfc(ast, ulnast, bili, ulnbili)hfc(ast, ulnast, bili, ulnbili)
ast |
Numeric vector of aspartate aminotransferase concentrations (IU/L) |
ulnast |
Numeric vector of upper limit of normal AST values (IU/L). Typically 33 IU/L for most laboratories |
bili |
Numeric vector of total bilirubin concentrations (mg/dL) |
ulnbili |
Numeric vector of upper limit of normal bilirubin values (mg/dL). Typically 1.2 mg/dL for most laboratories |
The NCI-ODWG hepatic function categories are defined as:
1: Normal: AST ≤ ULN AND bilirubin ≤ ULN
2: Mild impairment: AST > ULN OR bilirubin > ULN but ≤ 1.5 × ULN
3: Moderate impairment: Bilirubin > 1.5 × ULN but ≤ 3 × ULN
4: Severe impairment: Bilirubin > 3 × ULN
Special handling:
The function uses dplyr::near() for boundary comparisons when bilirubin
values are very close to 1.5 × ULN or 3 × ULN to handle floating-point precision
issues that can occur with calculated thresholds.
Integer vector of hepatic function categories (1-4). Returns the value of
getOption("scicalc.missing_value") (default -999) for
missing values.
National Cancer Institute Organ Dysfunction Working Group criteria for hepatic impairment
# Single patient with normal hepatic function hfc(ast = 15, ulnast = 33, bili = 0.6, ulnbili = 1.2) # Multiple patients with different impairment levels hfc(ast = c(25, 45, 30, 20), ulnast = c(33, 33, 33, 33), bili = c(0.8, 1.0, 2.5, 4.0), ulnbili = c(1.2, 1.2, 1.2, 1.2)) # Edge case: bilirubin exactly at boundary hfc(ast = 25, ulnast = 33, bili = 1.8, ulnbili = 1.2) # 1.8 = 1.5 * 1.2 # Pipeline example with realistic data library(dplyr) patients <- data.frame( ID = 1:6, AST = c(15, 45, 28, 35, 22, 30), ULNAST = 33, BILI = c(0.8, 1.0, 2.2, 4.5, 1.8, 0.9), ULNBILI = 1.2 ) patients |> mutate(BHFC = hfc(AST, ULNAST, BILI, ULNBILI))# Single patient with normal hepatic function hfc(ast = 15, ulnast = 33, bili = 0.6, ulnbili = 1.2) # Multiple patients with different impairment levels hfc(ast = c(25, 45, 30, 20), ulnast = c(33, 33, 33, 33), bili = c(0.8, 1.0, 2.5, 4.0), ulnbili = c(1.2, 1.2, 1.2, 1.2)) # Edge case: bilirubin exactly at boundary hfc(ast = 25, ulnast = 33, bili = 1.8, ulnbili = 1.2) # 1.8 = 1.5 * 1.2 # Pipeline example with realistic data library(dplyr) patients <- data.frame( ID = 1:6, AST = c(15, 45, 28, 35, 22, 30), ULNAST = 33, BILI = c(0.8, 1.0, 2.2, 4.5, 1.8, 0.9), ULNBILI = 1.2 ) patients |> mutate(BHFC = hfc(AST, ULNAST, BILI, ULNBILI))
Calculates ideal body weight using the Devine equation. By default, applies intercepts for individuals shorter than 5 feet (152.4 cm).
ibw(height, sexf, age, allow_ibw_lt_intercept = TRUE)ibw(height, sexf, age, allow_ibw_lt_intercept = TRUE)
height |
baseline height of subject in centimeters |
sexf |
0 = male, 1 = female, from sexf() |
age |
Numeric vector of baseline age in years. |
allow_ibw_lt_intercept |
logical indicating whether to apply intercepts for heights < 152.4 cm (5 feet). When TRUE (default), ideal weight is set to intercept weight (50 kg for males, 45.5 kg for females) |
The Devine equation for ideal body weight:
where:
= 50 kg (male) or 45.5 kg (female)
= height in inches (60 inches = 5 feet = 152.4 cm)
ideal body weight (kg)
The Origin of the "Ideal" Body Weight Equations, by Pai and Paloucek. The annals of Pharmacotherapy 2000 september, volumn 34
Other body_composition:
aibw(),
bmi(),
bmic(),
bsa()
df <- data.frame( ID = 1:6, HEIGHT = c(160, 170, 175, 165, 180, 150), SEX = c(1, 0, 0, 1, 0, 1), AGE = c(18, 27, 34, 33, 29, 30) ) df <- dplyr::mutate(df, IBW = ibw(HEIGHT, SEX, AGE)) dfdf <- data.frame( ID = 1:6, HEIGHT = c(160, 170, 175, 165, 180, 150), SEX = c(1, 0, 0, 1, 0, 1), AGE = c(18, 27, 34, 33, 29, 30) ) df <- dplyr::mutate(df, IBW = ibw(HEIGHT, SEX, AGE)) df
Check if Race is American Native
is_american_native(x)is_american_native(x)
x |
input character representing race |
boolean representing Race == American Native
Other demographics:
ethnicn(),
is_asian(),
is_black(),
is_female(),
is_hispanic_or_latino(),
is_not_hispanic_or_latino(),
is_other(),
is_pacific_islander(),
is_unspecified(),
is_white(),
racen(),
sexf()
is_american_native("AMERICAN INDIAN OR ALASKA NATIVE") is_american_native("BLACK") is_american_native(4)is_american_native("AMERICAN INDIAN OR ALASKA NATIVE") is_american_native("BLACK") is_american_native(4)
Check if Race is Asian
is_asian(x)is_asian(x)
x |
input character representing race |
boolean representing Race == Asian
Other demographics:
ethnicn(),
is_american_native(),
is_black(),
is_female(),
is_hispanic_or_latino(),
is_not_hispanic_or_latino(),
is_other(),
is_pacific_islander(),
is_unspecified(),
is_white(),
racen(),
sexf()
is_asian("ASIAN") is_asian("BLACK") is_asian(3)is_asian("ASIAN") is_asian("BLACK") is_asian(3)
Check if Race is Black
is_black(x)is_black(x)
x |
input character representing race |
boolean representing Race == Black
Other demographics:
ethnicn(),
is_american_native(),
is_asian(),
is_female(),
is_hispanic_or_latino(),
is_not_hispanic_or_latino(),
is_other(),
is_pacific_islander(),
is_unspecified(),
is_white(),
racen(),
sexf()
is_black("WHITE") is_black(c("AFRICAN AMERICAN", "BLACK")) is_black(2)is_black("WHITE") is_black(c("AFRICAN AMERICAN", "BLACK")) is_black(2)
Check if Sex is Female
is_female(x)is_female(x)
x |
input character representing female or male |
boolean representing female
Other demographics:
ethnicn(),
is_american_native(),
is_asian(),
is_black(),
is_hispanic_or_latino(),
is_not_hispanic_or_latino(),
is_other(),
is_pacific_islander(),
is_unspecified(),
is_white(),
racen(),
sexf()
is_female("F") is_female(c("MALE", "FEMALE")) is_female(c(1, 0, -999))is_female("F") is_female(c("MALE", "FEMALE")) is_female(c(1, 0, -999))
Check if Ethnicity is Hispanic or Latino
is_hispanic_or_latino(x)is_hispanic_or_latino(x)
x |
input character representing ethnicity |
boolean representing Ethnic == "Hispanic or Latino"
Other demographics:
ethnicn(),
is_american_native(),
is_asian(),
is_black(),
is_female(),
is_not_hispanic_or_latino(),
is_other(),
is_pacific_islander(),
is_unspecified(),
is_white(),
racen(),
sexf()
is_hispanic_or_latino("HISPANIC OR LATINO") is_hispanic_or_latino("NOT HISPANIC OR LATINO") is_hispanic_or_latino("UNKNOWN") is_hispanic_or_latino(1)is_hispanic_or_latino("HISPANIC OR LATINO") is_hispanic_or_latino("NOT HISPANIC OR LATINO") is_hispanic_or_latino("UNKNOWN") is_hispanic_or_latino(1)
Returns TRUE for elements equal to the missing value indicator
(getOption("scicalc.missing_value"), default -999), e.g.
dplyr::filter(df, !is_missing_value(NTFD)).
NA elements return FALSE (they are a separate representation of missing,
not the sentinel).
is_missing_value(x, missing_value = getOption("scicalc.missing_value", -999))is_missing_value(x, missing_value = getOption("scicalc.missing_value", -999))
x |
a numeric vector. |
missing_value |
the sentinel to test against. Defaults to
|
a logical vector the same length as x.
is_missing_value(c(1, -999, 3))is_missing_value(c(1, -999, 3))
Check if Ethnicity is Not Hispanic or Latino
is_not_hispanic_or_latino(x)is_not_hispanic_or_latino(x)
x |
input character representing ethnicity |
boolean representing Ethnic == "Not Hispanic or Latino"
Other demographics:
ethnicn(),
is_american_native(),
is_asian(),
is_black(),
is_female(),
is_hispanic_or_latino(),
is_other(),
is_pacific_islander(),
is_unspecified(),
is_white(),
racen(),
sexf()
is_not_hispanic_or_latino("HISPANIC OR LATINO") is_not_hispanic_or_latino("NOT HISPANIC OR LATINO") is_not_hispanic_or_latino("UNKNOWN") is_not_hispanic_or_latino(0)is_not_hispanic_or_latino("HISPANIC OR LATINO") is_not_hispanic_or_latino("NOT HISPANIC OR LATINO") is_not_hispanic_or_latino("UNKNOWN") is_not_hispanic_or_latino(0)
Check if Race is Other
is_other(x)is_other(x)
x |
input character representing race |
boolean representing Race == Other
Other demographics:
ethnicn(),
is_american_native(),
is_asian(),
is_black(),
is_female(),
is_hispanic_or_latino(),
is_not_hispanic_or_latino(),
is_pacific_islander(),
is_unspecified(),
is_white(),
racen(),
sexf()
is_other("OTHER") is_other("MULTIPLE") is_other("BLACK") is_other(6)is_other("OTHER") is_other("MULTIPLE") is_other("BLACK") is_other(6)
Check if Race is Pacific Islander
is_pacific_islander(x)is_pacific_islander(x)
x |
input character representing race |
boolean representing Race == Pacific Islander
Other demographics:
ethnicn(),
is_american_native(),
is_asian(),
is_black(),
is_female(),
is_hispanic_or_latino(),
is_not_hispanic_or_latino(),
is_other(),
is_unspecified(),
is_white(),
racen(),
sexf()
is_pacific_islander("NATIVE HAWAIIAN OR OTHER PACIFIC ISLANDER") is_pacific_islander("BLACK") is_pacific_islander(5)is_pacific_islander("NATIVE HAWAIIAN OR OTHER PACIFIC ISLANDER") is_pacific_islander("BLACK") is_pacific_islander(5)
TRUE for a race value that is present but matches none of the known
categories (is_white, is_black, is_asian, is_american_native,
is_pacific_islander, is_other). "unknown" and NA are treated as
missing (not unspecified) and return FALSE. When unspecified values are
found a warning is emitted naming the distinct offenders.
is_unspecified(x, known = character(0))is_unspecified(x, known = character(0))
x |
input character representing race |
known |
optional character vector of additional recognized values to
treat as specified (used by |
boolean representing an unrecognized race value
Other demographics:
ethnicn(),
is_american_native(),
is_asian(),
is_black(),
is_female(),
is_hispanic_or_latino(),
is_not_hispanic_or_latino(),
is_other(),
is_pacific_islander(),
is_white(),
racen(),
sexf()
is_unspecified("ROMAN LATIN") is_unspecified("WHITE") is_unspecified("UNKNOWN")is_unspecified("ROMAN LATIN") is_unspecified("WHITE") is_unspecified("UNKNOWN")
Check if Race is White
is_white(x)is_white(x)
x |
input character representing race |
boolean representing Race == White
Other demographics:
ethnicn(),
is_american_native(),
is_asian(),
is_black(),
is_female(),
is_hispanic_or_latino(),
is_not_hispanic_or_latino(),
is_other(),
is_pacific_islander(),
is_unspecified(),
racen(),
sexf()
is_white("WHITE") is_white("BLACK") is_white(1)is_white("WHITE") is_white("BLACK") is_white(1)
Convert Race to Numeric Code
racen(racec)racen(racec)
racec |
Race character |
Default mapping: White = 1, Black = 2, Asian = 3, American Native = 4,
Pacific Islander = 5, Other = 6. "UNKNOWN" and NA map to the missing
value indicator (getOption("scicalc.missing_value", -999)). Any other
value is treated as unspecified: it maps to NA and triggers a warning.
The scicalc.racen_config option (a named numeric vector) customizes the
mapping. A name matching a built-in category ("white", "black",
"asian", "american native", "pacific islander", "other") overrides
that category's code (synonyms included). Any other name adds a new
exact-match category. For example
options(scicalc.racen_config = c("WHITE" = 2, "JAPANESE" = 7)).
the standard yspec numeric value for the inputted Race character
Other demographics:
ethnicn(),
is_american_native(),
is_asian(),
is_black(),
is_female(),
is_hispanic_or_latino(),
is_not_hispanic_or_latino(),
is_other(),
is_pacific_islander(),
is_unspecified(),
is_white(),
sexf()
racen("WHITE") # 1 racen("BLACK") # 2 racen("ASIAN") # 3 racen("AMERICAN INDIAN OR ALASKA NATIVE") # 4 racen("PACIFIC ISLANDER") # 5 racen("OTHER") # 6 racen("UNKNOWN") # default missing valueracen("WHITE") # 1 racen("BLACK") # 2 racen("ASIAN") # 3 racen("AMERICAN INDIAN OR ALASKA NATIVE") # 4 racen("PACIFIC ISLANDER") # 5 racen("OTHER") # 6 racen("UNKNOWN") # default missing value
Read CSV File with Hash Verification
read_csv_with_hash(csv_file_path, ..., algo = "blake3")read_csv_with_hash(csv_file_path, ..., algo = "blake3")
csv_file_path |
path to csv file to ingest |
... |
additional arguments for digest or read_csv |
algo |
hashing algorithm to use, default is "blake3" |
dataframe of data within file
## Not run: read_csv_with_hash("data/derived/example_data.csv") ## End(Not run)## Not run: read_csv_with_hash("data/derived/example_data.csv") ## End(Not run)
Read Excel File with Hash Verification
read_excel_with_hash(xlsx_file_path, ..., algo = "blake3")read_excel_with_hash(xlsx_file_path, ..., algo = "blake3")
xlsx_file_path |
an xlsx/xls file to ingest |
... |
additional arguments to digest or read_excel |
algo |
hashing algorithm to use, default is "blake3" |
a dataframe(?) of data within file
## Not run: read_excel_with_hash("data/source/example.xpt") ## End(Not run)## Not run: read_excel_with_hash("data/source/example.xpt") ## End(Not run)
Read Data File with Hash Verification
read_file_with_hash( file_path, ..., algo = "blake3", reader = NULL, force = FALSE )read_file_with_hash( file_path, ..., algo = "blake3", reader = NULL, force = FALSE )
file_path |
path to data file |
... |
additional arguments to digest, read_csv, read_parquet, read_sas, read_pzfx, read_xpt, or |
algo |
hashing algorithm to use, default is "blake3" |
reader |
optional function used to read the file, called as |
force |
if |
data within the supplied file, carrying file_hash and data_hash attributes
Other file_io:
read_hashed_file(),
write_file_with_hash()
## Not run: dat <- read_file_with_hash("data/derived/PK_data.parquet") dat2 <- read_file_with_hash("data/source/data.csv") dat3 <- read_file_with_hash("data/derived/pk.feather", reader = arrow::read_feather) ## End(Not run)## Not run: dat <- read_file_with_hash("data/derived/PK_data.parquet") dat2 <- read_file_with_hash("data/source/data.csv") dat3 <- read_file_with_hash("data/derived/pk.feather", reader = arrow::read_feather) ## End(Not run)
Read File with Required Hash Match
read_hashed_file( file_path, hash, ..., algo = "blake3", reader = NULL, force = FALSE )read_hashed_file( file_path, hash, ..., algo = "blake3", reader = NULL, force = FALSE )
file_path |
path to file with data you want to read |
hash |
hash you expect the file to have |
... |
additional arguments for digest or read_csv, parquet, sas, or |
algo |
hashing algorithm to use, default is "blake3" |
reader |
optional function used to read the file, called as |
force |
if |
data object of contents of file_path
Other file_io:
read_file_with_hash(),
write_file_with_hash()
## Not run: file_path <- "data/derived/example_pk.parquet" hash <- 0cfd6da55e6c1e198effe1e584c26d79 read_hashed_file(file_path, hash) ## End(Not run)## Not run: file_path <- "data/derived/example_pk.parquet" hash <- 0cfd6da55e6c1e198effe1e584c26d79 read_hashed_file(file_path, hash) ## End(Not run)
Read Parquet File with Hash Verification
read_parquet_with_hash(parquet_file_path, ..., algo = "blake3")read_parquet_with_hash(parquet_file_path, ..., algo = "blake3")
parquet_file_path |
path to parquet file to ingest |
... |
additional arguments to digest or read_parquet |
algo |
hashing algorithm to use, default is "blake3" |
a tibble of data within file
## Not run: read_parquet_with_hash("data/derived/example_data.parquet") ## End(Not run)## Not run: read_parquet_with_hash("data/derived/example_data.parquet") ## End(Not run)
Read Prism PZFX File with Hash Verification
read_pzfx_with_hash(pzfx_file_path, ..., algo = "blake3")read_pzfx_with_hash(pzfx_file_path, ..., algo = "blake3")
pzfx_file_path |
path to pzfx file |
... |
additional arguments to digest or read_pzfx |
algo |
hashing algorithm to use, default is "blake3" |
data within the table of the pzfx file
## Not run: read_pzfx_with_hash("mydata.pzfx", table = "experiment1") ## End(Not run)## Not run: read_pzfx_with_hash("mydata.pzfx", table = "experiment1") ## End(Not run)
Read SAS File with Hash Verification
read_sas_with_hash(sas_file_path, ..., algo = "blake3")read_sas_with_hash(sas_file_path, ..., algo = "blake3")
sas_file_path |
path to sas file to ingest |
... |
additional arguments to digest or read_sas |
algo |
hashing algorithm to use, default is "blake3" |
a dataframe(?) of data within file
## Not run: read_sas_with_hash("data/source/example.sas7bdat") ## End(Not run)## Not run: read_sas_with_hash("data/source/example.sas7bdat") ## End(Not run)
Read XPT File with Hash Verification
read_xpt_with_hash(xpt_file_path, ..., algo = "blake3")read_xpt_with_hash(xpt_file_path, ..., algo = "blake3")
xpt_file_path |
an xpt file to ingest |
... |
additional arguments to digest or read_xpt |
algo |
hashing algorithm to use, default is "blake3" |
a dataframe(?) of data within file
## Not run: read_xpt_with_hash("data/source/example.xpt") ## End(Not run)## Not run: read_xpt_with_hash("data/source/example.xpt") ## End(Not run)
This function categorizes renal function based on estimated glomerular filtration rate (eGFR), creatinine clearance, or other renal function estimators. It supports both clinical and regulatory categorization standards and can convert between absolute (mL/min) and relative (mL/min/1.73m²) units using body surface area.
rfc( estimator = NULL, bsa = NULL, category_standard = c("regulatory", "clinical"), absolute_units = NULL )rfc( estimator = NULL, bsa = NULL, category_standard = c("regulatory", "clinical"), absolute_units = NULL )
estimator |
Numeric vector of renal function estimator values (eGFR, CrCL, etc.) |
bsa |
Numeric vector of body surface area in m² for unit conversion. Required when converting between absolute and relative units |
category_standard |
Character string specifying categorization standard:
|
absolute_units |
Logical: are |
The function applies different categorization schemes based on the category_standard:
Regulatory categories (uses mL/min):
1: Normal: ≥90 mL/min
2: Mild impairment: 60-89 mL/min
3: Moderate impairment: 30-59 mL/min
4: Severe impairment: <30 mL/min
Clinical categories (uses mL/min/1.73m²):
1: Normal: ≥90 mL/min/1.73m²
2: Mild impairment: 60-89 mL/min/1.73m²
3: Moderate impairment: 30-59 mL/min/1.73m²
4: Severe impairment: 15-29 mL/min/1.73m²
5: End-stage: <15 mL/min/1.73m²
When unit conversion is required, the function uses:
Absolute to relative: relative = 1.73 (absolute / bsa)
Relative to absolute: absolute = relative (bsa / 1.73)
Integer vector of renal impairment categories (1-4 for regulatory, 1-5 for clinical).
Returns the value of getOption("scicalc.missing_value") (default -999)
for missing values. Includes a category_standard attribute
indicating the source ("FDA" or "KDIGO").
FDA Guidance for Industry: Pharmacokinetics in Patients with Impaired Renal Function. https://www.fda.gov/media/78573/download
KDIGO 2024 Clinical Practice Guideline for the Evaluation and Management of Chronic Kidney Disease. https://www.kidney-international.org/action/showPdf?pii=S0085-2538(23)00766-4
egfr for calculating eGFR, crcl for creatinine clearance,
bsa for body surface area calculation
Other renal_function:
aegfr(),
crcl(),
egfr()
# Regulatory categories with absolute units (creatinine clearance) rfc(estimator = c(95, 75, 45, 25), absolute_units = TRUE) # Clinical categories with relative units (eGFR) rfc( estimator = c(95, 75, 45, 25, 10), absolute_units = FALSE, category_standard = "clinical" ) # Convert relative eGFR to regulatory categories rfc( estimator = 65, absolute_units = FALSE, bsa = 1.8 ) # Pipeline example with realistic data df <- data.frame( ID = 1:4, SEX = c("F", "M", "F", "M"), AGE = c(65, 45, 70, 50), CREAT = c(1.2, 0.9, 1.5, 1.1), WEIGHT = c(70, 80, 60, 85), HEIGHT = c(165, 175, 160, 180), RACE = c("WHITE", "BLACK", "OTHER", "ASIAN") ) library(dplyr) df <- df |> mutate( BSA = bsa(WEIGHT, HEIGHT, method = "Dubois"), EGFR = egfr(is_female(SEX), is_black(RACE), AGE, CREAT), AEGFR = aegfr(EGFR, BSA), # Clinical categories using relative eGFR directly BRFC_CLINICAL = rfc(EGFR, category_standard = "clinical"), # Regulatory categories - convert relative eGFR to absolute BRFC_REGULATORY_REL = rfc(EGFR, BSA), # Regulatory categories - AEGFR already absolute BRFC_REGULATORY_ABS = rfc(AEGFR) ) df# Regulatory categories with absolute units (creatinine clearance) rfc(estimator = c(95, 75, 45, 25), absolute_units = TRUE) # Clinical categories with relative units (eGFR) rfc( estimator = c(95, 75, 45, 25, 10), absolute_units = FALSE, category_standard = "clinical" ) # Convert relative eGFR to regulatory categories rfc( estimator = 65, absolute_units = FALSE, bsa = 1.8 ) # Pipeline example with realistic data df <- data.frame( ID = 1:4, SEX = c("F", "M", "F", "M"), AGE = c(65, 45, 70, 50), CREAT = c(1.2, 0.9, 1.5, 1.1), WEIGHT = c(70, 80, 60, 85), HEIGHT = c(165, 175, 160, 180), RACE = c("WHITE", "BLACK", "OTHER", "ASIAN") ) library(dplyr) df <- df |> mutate( BSA = bsa(WEIGHT, HEIGHT, method = "Dubois"), EGFR = egfr(is_female(SEX), is_black(RACE), AGE, CREAT), AEGFR = aegfr(EGFR, BSA), # Clinical categories using relative eGFR directly BRFC_CLINICAL = rfc(EGFR, category_standard = "clinical"), # Regulatory categories - convert relative eGFR to absolute BRFC_REGULATORY_REL = rfc(EGFR, BSA), # Regulatory categories - AEGFR already absolute BRFC_REGULATORY_ABS = rfc(AEGFR) ) df
Priority:
If sdig is provided, round x to that many significant digits.
If sdig is NULL but ref is provided, infer the number of significant digits from ref.
If both are NULL, return x unchanged.
round_like(x, ref = NULL, sdig = NULL)round_like(x, ref = NULL, sdig = NULL)
x |
Numeric vector to round. |
ref |
Optional numeric vector used to infer the number of significant digits. |
sdig |
Optional integer specifying the number of significant digits to apply. |
A numeric vector rounded to the appropriate precision.
round_like(123.456, sdig = 2) # -> 120 round_like(123.456, ref = 12.3) # -> 123 round_like(123.456, ref = 12.34) # -> 123.5 round_like(123.456) # -> 123.456round_like(123.456, sdig = 2) # -> 120 round_like(123.456, ref = 12.3) # -> 123 round_like(123.456, ref = 12.34) # -> 123.5 round_like(123.456) # -> 123.456
Also returns numeric for single character Sex characters "F" and "M"
sexf(sex)sexf(sex)
sex |
Sex character |
the standard yspec numeric value for the inputted Sex character
Other demographics:
ethnicn(),
is_american_native(),
is_asian(),
is_black(),
is_female(),
is_hispanic_or_latino(),
is_not_hispanic_or_latino(),
is_other(),
is_pacific_islander(),
is_unspecified(),
is_white(),
racen()
sexf("FEMALE") # 1 sexf("female") # 1 sexf("f") # 1 sexf("MALE") # 0 sexf("NOT SPECIFIED") # 0sexf("FEMALE") # 1 sexf("female") # 1 sexf("f") # 1 sexf("MALE") # 0 sexf("NOT SPECIFIED") # 0
Write Data File with Hash Output
write_file_with_hash( data, path, overwrite = FALSE, ..., algo = "blake3", writer = NULL, force = FALSE )write_file_with_hash( data, path, overwrite = FALSE, ..., algo = "blake3", writer = NULL, force = FALSE )
data |
the data object to write to file |
path |
the destination of the file (csv or parquet) |
overwrite |
boolean of whether to overwrite or not. |
... |
additional arguments for digest, write_csv, write_parquet, or |
algo |
hashing algorithm to use, default is "blake3" |
writer |
optional function used to write the file, called as |
force |
if |
Nothing, File is created and hash of created file is printed
Other file_io:
read_file_with_hash(),
read_hashed_file()
## Not run: df <- data.frame( "a" = c(1, 2, 3, 4) "b" = c("A", "B", "C", "D") ) write_file_with_hash(df, "data.csv") write_file_with_hash(df, "data.rds", writer = saveRDS) ## End(Not run)## Not run: df <- data.frame( "a" = c(1, 2, 3, 4) "b" = c("A", "B", "C", "D") ) write_file_with_hash(df, "data.csv") write_file_with_hash(df, "data.rds", writer = saveRDS) ## End(Not run)