File: subsetting-matrix.R

package info (click to toggle)
r-cran-tibble 3.1.8%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 2,008 kB
  • sloc: ansic: 317; sh: 10; makefile: 5
file content (93 lines) | stat: -rw-r--r-- 2,518 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
tbl_subset_matrix <- function(x, j, j_arg) {
  cells <- matrix_to_cells(j, x, j_arg)
  col_idx <- cells_to_col_idx(cells)

  if (is_empty(col_idx)) {
    return(unspecified())
  }

  values <- map2(x[col_idx], cells[col_idx], vec_slice)

  # Also checks conformity of vectors:
  unname(vec_c(!!!values, .name_spec = ~.x))
}

tbl_subassign_matrix <- function(x, j, value, j_arg, value_arg) {
  # FIXME: use size argument in vctrs >= 0.3.0

  if (!vec_is(value)) {
    cnd_signal(error_subset_matrix_scalar_type(j_arg, value_arg))
  }

  if (vec_size(value) != 1) {
    cnd_signal(error_subset_matrix_must_be_scalar(j_arg, value_arg))
  }

  cells <- matrix_to_cells(j, x, j_arg)
  col_idx <- cells_to_col_idx(cells)

  withCallingHandlers(
    for (j in col_idx) {
      x[[j]] <- vectbl_assign(x[[j]], cells[[j]], value)
    },
    vctrs_error_incompatible_type = function(cnd) {
      cnd_signal(error_assign_incompatible_type(x, rep(list(value), j), j, value_arg, cnd_message(cnd)))
    }
  )

  x
}

matrix_to_cells <- function(j, x, j_arg) {
  if (!is_bare_logical(j)) {
    cnd_signal(error_subset_matrix_must_be_logical(j_arg))
  }
  if (!identical(dim(j), dim(x))) {
    cnd_signal(error_subset_matrix_must_have_same_dimensions(j_arg))
  }

  # Need unlist(list(...)) because apply() isn't type stable if the return
  # has the same length everywhere
  # FIXME: Faster with a C implementation?
  cells <- unlist(apply(j, 2, function(x) list(which(x))), recursive = FALSE)
  cells
}

cells_to_col_idx <- function(cells) {
  sizes <- map_int(cells, vec_size)
  col_idx <- which(sizes > 0)

  col_idx
}

# Errors ------------------------------------------------------------------

error_subset_matrix_must_be_logical <- function(j_arg) {
  tibble_error(paste0(
    "Subscript ", tick(as_label(j_arg)),
    " is a matrix, it must be of type logical."
  ))
}

error_subset_matrix_must_have_same_dimensions <- function(j_arg) {
  tibble_error(paste0(
    "Subscript ", tick(as_label(j_arg)),
    " is a matrix, it must have the same dimensions as the input."
  ))
}

error_subset_matrix_scalar_type <- function(j_arg, value_arg) {
  tibble_error(paste0(
    "Subscript ", tick(as_label(j_arg)),
    " is a matrix, the data ", tick(as_label(value_arg)),
    " must be a vector of size 1."
  ))
}

error_subset_matrix_must_be_scalar <- function(j_arg, value_arg) {
  tibble_error(paste0(
    "Subscript ", tick(as_label(j_arg)),
    " is a matrix, the data ", tick(as_label(value_arg)),
    " must have size 1."
  ))
}