#' Convert all units, regardless of starting and ending units
#'
#' @param meas A measurement in any unit of length
#' @param from_unit A string containing the original unit of measure to be
#' converted
#' @param to_unit A string containing the ending unit of measure
#' @param conversion_columns A vector containing the columns to convert if
#' \code{meas} is of type \code{data.frame}
#'
#' @return The measurement in converted units
#'
#' @export
#'
#' @examples
#' convert_units(1, "in", "cm")
#' convert_units(100, "cm", "m")
convert_units <- function(meas,
from_unit,
to_unit,
conversion_columns = NULL) {
# Convert the from_unit and to_unit to be lower case
from_unit <- tolower(from_unit)
to_unit <- tolower(to_unit)
# Create the conversion table
conversion_table <- data.frame(
unit_name = c(
"millimeters",
"centimeters",
"meters",
"inches",
"feet",
"yards"
),
unit_abbreviation = c(
"mm",
"cm",
"m",
"in",
"ft",
"yd"
),
conversion_factor = c(
304.8,
30.48,
0.3048,
12,
1,
1 / 3
)
)
# Ensure that the from_unit and to_unit exist somewhere in the conversion
# table
if (!(from_unit %in% conversion_table$unit_abbreviation) &&
!(from_unit %in% conversion_table$unit_name)) {
stop(glue::glue("{from_unit} is not a viable unit at this time."))
}
if (!(to_unit %in% conversion_table$unit_abbreviation) &&
!(to_unit %in% conversion_table$unit_name)) {
stop(glue::glue("{to_unit} is not a viable unit at this time."))
}
# This function should work over entire data frames as well as individual
# vectors
if (is.data.frame(meas)) {
# If no columns are supplied, alert user of error
if (is.null(conversion_columns)) {
stop(glue::glue("Must supply columns to convert"))
}
# Iterate over the supplied columns and perform the conversion
for (column in conversion_columns) {
# Check to ensure the column name is in the data frame's column names
if (!(column %in% names(meas))) {
message(
glue::glue(
"{column} is not a column in the supplied data frame. Skipping..."
)
)
} else if (class(meas[, column]) %in% c("integer", "numeric")) {
# Columns must be either integer or numeric in type
if (from_unit %in% conversion_table$unit_abbreviation &&
to_unit %in% conversion_table$unit_abbreviation) {
meas[column] <- meas[column] /
conversion_table[
conversion_table$unit_abbreviation == from_unit,
"conversion_factor"
]
meas[column] <- meas[column] *
conversion_table[
conversion_table$unit_abbreviation == to_unit,
"conversion_factor"
]
} else if (from_unit %in% conversion_table$unit_abbreviation &&
to_unit %in% conversion_table$unit_name) {
meas[column] <- meas[column] /
conversion_table[
conversion_table$unit_abbreviation == from_unit,
"conversion_factor"
]
meas[column] <- meas[column] *
conversion_table[
conversion_table$unit_name == to_unit,
"conversion_factor"
]
} else if (from_unit %in% conversion_table$unit_name &&
to_unit %in% conversion_table$unit_abbreviation) {
meas[column] <- meas[column] /
conversion_table[
conversion_table$unit_name == from_unit,
"conversion_factor"
]
meas[column] <- meas[column] *
conversion_table[
conversion_table$unit_abbreviation == to_unit,
"conversion_factor"
]
} else {
meas[column] <- meas[column] /
conversion_table[
conversion_table$unit_name == from_unit,
"conversion_factor"
]
meas[column] <- meas[column] *
conversion_table[
conversion_table$unit_name == to_unit,
"conversion_factor"
]
}
} else {
# If a supplied column is neither of type integer or numeric, alert user
# that the column is
message(glue::glue("{column} is not convertable. Skipping..."))
}
}
# Return the data frame
return(meas)
} else {
# Perform the conversion by first converting the input into the base unit,
# then converting to the desired unit
if (from_unit %in% conversion_table$unit_abbreviation &&
to_unit %in% conversion_table$unit_abbreviation) {
reduced <- meas /
conversion_table[
conversion_table$unit_abbreviation == from_unit,
"conversion_factor"
]
result <- reduced *
conversion_table[
conversion_table$unit_abbreviation == to_unit,
"conversion_factor"
]
} else if (from_unit %in% conversion_table$unit_abbreviation &&
to_unit %in% conversion_table$unit_name) {
reduced <- meas /
conversion_table[
conversion_table$unit_abbreviation == from_unit,
"conversion_factor"
]
result <- reduced *
conversion_table[
conversion_table$unit_name == to_unit,
"conversion_factor"
]
} else if (from_unit %in% conversion_table$unit_name &&
to_unit %in% conversion_table$unit_abbreviation) {
reduced <- meas /
conversion_table[
conversion_table$unit_name == from_unit,
"conversion_factor"
]
result <- reduced *
conversion_table[
conversion_table$unit_abbreviation == to_unit,
"conversion_factor"
]
} else {
reduced <- meas /
conversion_table[
conversion_table$unit_name == from_unit,
"conversion_factor"
]
result <- reduced *
conversion_table[
conversion_table$unit_name == to_unit,
"conversion_factor"
]
}
# Return the converted measurement
return(result)
}
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.