Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replacing positive table values with positive values from a list of uneven vectors

Tags:

list

r

vector

Background

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.

Problem

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 

Previous answer

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.

Suggestion

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.

like image 850
Tom Avatar asked Jan 27 '26 10:01

Tom


1 Answers

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
like image 104
Darren Tsai Avatar answered Jan 29 '26 23:01

Darren Tsai



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!