I recently asked this question. I however made the example slightly too simple, so I am adding some complexity here, where the vector length is no longer equal to the table length.
I have a table as follows:
tableA <- structure(c(1L, 0L, 0L, 0L, 4L, 6L, 0L, 6L, 1L, 3L, 0L, 0L, 0L, 0L, 1L), dim = c(3L,
5L), dimnames = structure(list(c("X", "Y",
"Z"), c("A", "B", "C","D", "E")), names = c("", "")), class = "table")
A B C D E
X 1 0 0 3 0 (two positive numbers)
Y 0 4 6 0 0 (two positive numbers)
Z 0 6 1 0 1 (three positive numbers)
And a list of vectors as follows:
listB <- list(
"X" = c(0, 4),
"Y" = c(4, 5),
"Z" = c(7, 1, 0))
The vectors are not equal, but the amount of numbers in the vectors equal the amount positive numbers in the table.
I would like to replace all values in tableA, of columns B,C, and D, that are bigger than zero, with the corresponding values of listB.
Desired output:
A B C D E
X 1 0 0 4 0
Y 0 4 5 0 0
Z 0 7 1 0 1
The original answer by sindri_baldur suggested the following:
cols2replace = match(c('B', 'C', 'D'), colnames(tableA))
cells2replace = tableA[, cols2replace] > 0
tableB = matrix(unlist(listB), nrow = 3, byrow = TRUE)
tableA[, cols2replace][cells2replace] = tableB[, cols2replace][cells2replace]
In my actual data however the vectors in the list of vectors are unequal. Therefore:
tableB = matrix(unlist(listB), nrow = 3, byrow = TRUE)
Does not work.
I am wondering if I cannot simply get all positive values from tableA, replace them with all positive values of of listB (so that values which are 0 in listB are not replaced) and then put them back in the table. I started as follows:
# Get all positive values from the table
library(dplyr)
library(tidyr)
library(stringr)
out <- tableA %>%
pivot_longer(cols = -rn) %>%
filter(str_detect(value, '\\b0\\b', negate = TRUE)) %>%
group_by(rn) %>%
summarise(freq = list(value), .groups = 'drop')
But the code does not work on a table.
Assume the amount of numbers in each vector in listB equals the amount of positive numbers in each row of tableA, you could solve it by
tab <- t(tableA)
tab[tab > 0] <- unlist(listB)
tableA[, c('B', 'C', 'D')] <- t(tab)[, c('B', 'C', 'D')]
tableA
# A B C D E
# X 1 0 0 4 0
# Y 0 4 5 0 0
# Z 0 7 1 0 1
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With