1# Fast data.frame constructor and indexing 2# No checking, recycling etc. unless asked for 3new_data_frame <- function(x = list(), n = NULL) { 4 if (length(x) != 0 && is.null(names(x))) { 5 abort("Elements must be named") 6 } 7 lengths <- vapply(x, length, integer(1)) 8 if (is.null(n)) { 9 n <- if (length(x) == 0 || min(lengths) == 0) 0 else max(lengths) 10 } 11 for (i in seq_along(x)) { 12 if (lengths[i] == n) next 13 if (lengths[i] != 1) { 14 abort("Elements must equal the number of rows or 1") 15 } 16 x[[i]] <- rep(x[[i]], n) 17 } 18 19 class(x) <- "data.frame" 20 21 attr(x, "row.names") <- .set_row_names(n) 22 x 23} 24 25data_frame <- function(...) { 26 new_data_frame(list(...)) 27} 28 29split_matrix <- function(x, col_names = colnames(x)) { 30 force(col_names) 31 x <- lapply(seq_len(ncol(x)), function(i) x[, i]) 32 if (!is.null(col_names)) names(x) <- col_names 33 x 34} 35 36mat_2_df <- function(x, col_names = colnames(x)) { 37 new_data_frame(split_matrix(x, col_names)) 38} 39 40df_col <- function(x, name) .subset2(x, name) 41 42df_rows <- function(x, i) { 43 new_data_frame(lapply(x, `[`, i = i)) 44} 45 46# More performant modifyList without recursion 47modify_list <- function(old, new) { 48 for (i in names(new)) old[[i]] <- new[[i]] 49 old 50} 51modifyList <- function(...) { 52 abort(glue(" 53 Please use `modify_list()` instead of `modifyList()` for better performance. 54 See the vignette 'ggplot2 internal programming guidelines' for details. 55 ")) 56} 57