0

I have a vector p and a matrix Z. If values become negative in the first equation below, I would like to multiply them by a scaling factor sf. I have applied this for column 3 now, but my real data is a huge matrix, so how can I write an argument that finds all negative values, calculates sf and then multiplies them by the sf equation for that specific cell?

data:

p <- c(12,  10, 5,  8) 

Z <- read.table(header=FALSE, 
text=" 0    5   2   3
2   0   2   1
10  3   0   0
1   2   3   0
")     

code:

p + colSums(Z)-rowSums(Z) #if negative in this equation, then find  scaling factor sf:

sf <- (p[[3]] + colSums(Z[3])) / rowSums(Z[3,]) #scaling factor

(Z[3,]) * sf #multiply the negative value with scaling factor
Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
MoonS
  • 117
  • 7

1 Answers1

1

I think this should work:

test <- p + colSums(Z) - rowSums(Z)
sf <- (p + colSums(Z)) / rowSums(Z)
multiplier = ifelse(test < 0, sf, 1)
result <- diag(multiplier) %*% as.matrix(Z)

result
#            V1       V2 V3 V4
# [1,] 0.000000 5.000000  2  3
# [2,] 2.000000 0.000000  2  1
# [3,] 9.230769 2.769231  0  0
# [4,] 1.000000 2.000000  3  0

If your matrix is really big, it's inefficient above to calculate the row sums and col sums twice each, we could improve it a little bit by saving and re-using those results:

cs = colSums(Z)
rs = rowSums(Z)
test <- p + cs - rs
sf <- (p + cs) / rs
multiplier = ifelse(test < 0, sf, 1)
result <- diag(multiplier) %*% as.matrix(Z)
Gregor Thomas
  • 136,190
  • 20
  • 167
  • 294
  • This worked in my small example - but in "result" in my large matrix, I would like to keep the values from Z that do not need scaling. By taking diag(multiplier), I now get a lot of zeros in the result. Is it possible to add to this to the code? – MoonS Nov 24 '20 at 14:43
  • I'm confused - in the small example rows 1, 2, and 4 are not scaled and this method keeps the original values untouched in those rows.That's the point of the `multiplier = ifelse(test < 0, sf, 1)` multiplier line - rows with only a 1 in the diagonal are unchanged by matrix multiplication. What's different in your larger data? – Gregor Thomas Nov 24 '20 at 15:13
  • Note that my code doesn't work on row 3 only - it applies the operation to the entire matrix. – Gregor Thomas Nov 24 '20 at 15:18