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