Nothing
#' Helpers for Working With Row Names
#'
#' Easily move row names to a column and vice-versa without the unwanted
#' side-effects to object class and attributes. Drop-in replacement for
#' `tibble::rownames_to_column()` and `tibble::column_to_rownames()` which
#' can have undesired side-effects to complex object attributes.
#' Does not import any external packages, modify the environment, or change
#' the object (other than the desired column). When using [col2rn()], if
#' explicit row names exist, they are overwritten with a warning. [add_rowid()]
#' does *not* affect row names, which differs from `tibble::rowid_to_column()`.
#'
#' @name rownames
#' @param data An object that inherits from class `data.frame`. Typically
#' a `soma_adat` class object.
#' @param name Character. The name of the column to move.
#' @param value Character. The new set of names for the data frame.
#' If duplicates exist they are modified on-the-fly via [make.unique()].
#' @return All functions attempt to return an object of the same class as
#' the input with fully intact and unmodified attributes (aside from those
#' required by the desired action). [has_rn()] returns a scalar logical.
#' @examples
#' df <- data.frame(a = 1:5, b = rnorm(5), row.names = LETTERS[1:5])
#' df
#' rn2col(df) # default name is `.rn`
#' rn2col(df, "AptName") # pass `name =`
#'
#' # moving columns
#' df$mtcars <- sample(names(mtcars), 5)
#' col2rn(df, "mtcars") # with a warning
#'
#' # Move back and forth easily
#' # Leaves original object un-modified
#' identical(df, col2rn(rn2col(df)))
#'
#' # add "id" column
#' add_rowid(mtcars)
#'
#' # remove row names
#' has_rn(mtcars)
#' mtcars2 <- rm_rn(mtcars)
#' has_rn(mtcars2)
NULL
#' @describeIn rownames
#' moves the row names of `data` to an explicit column
#' whether they are explicit or implicit.
#' @export
rn2col <- function(data, name = ".rn") {
stopifnot(is.data.frame(data), length(name) == 1L)
nc <- ncol(data)
data[[name]] <- rownames(data)
data <- data[, c(nc + 1L, seq_len(nc))]
rm_rn(data)
}
#' @describeIn rownames
#' is the inverse of [rn2col()]. If row names exist, they
#' will be overwritten (with warning).
#' @export
col2rn <- function(data, name = ".rn") {
stopifnot(is.data.frame(data), length(name) == 1L)
if ( has_rn(data) ) {
warning("`", deparse(substitute(data)),
"` already has row names. They will be over-written.",
call. = FALSE
)
}
# order important
# ensure method dispatch during NextMethod()
value <- data[[name]]
data[[name]] <- NULL
set_rn(data, value)
}
#' @describeIn rownames
#' returns a boolean indicating whether the data frame
#' has explicit row names assigned.
#' @export
has_rn <- function(data) {
.row_names_info(data, 1L) > 0L && !is.na(.row_names_info(data, 0L)[[1L]])
}
# does the data frame have implicit rownames?
has_implicit_rn <- function(data) {
.row_names_info(data, 1L) < 0L
}
#' @describeIn rownames
#' removes existing row names, leaving only "implicit" row names.
#' @export
rm_rn <- function(data) {
stopifnot(is.data.frame(data))
set_rn(data, NULL)
}
#' @describeIn rownames
#' sets (and overwrites) existing row names for data frames only.
#' @export
set_rn <- function(data, value) {
stopifnot("`data` must be a data.frame." = is.data.frame(data))
if ( !is.null(value) ) {
value <- as.character(value)
if ( any(duplicated(value)) ) {
value <- make.unique(value, sep = "-")
}
}
rownames(data) <- value
data
}
#' @describeIn rownames
#' adds a sequential integer row identifier; starting at `1:nrow(data)`.
#' It does *not* remove existing row names currently, but may in the future
#' (please code accordingly).
#' @export
add_rowid <- function(data, name = ".rowid") {
stopifnot(is.data.frame(data), length(name) == 1L)
nc <- ncol(data)
data[[name]] <- seq_len(nrow(data))
data <- data[, c(nc + 1L, seq_len(nc))]
data
}
#' @export
`row.names<-.soma_adat` <- function(x, value) {
# directly to data.frame dispatch; skip tbl and warning
return(`row.names<-.data.frame`(x, value))
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.