Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R - Divide each value in matrix by maximum value of its row/column

I'm trying to transform the values in a matrix by dividing each value by the lesser of the maximum values of its column or row name. I am having trouble because I don't know how to query the row/column for a particular value from inside a larger function.

A small cut of the data looks like this: a weighted (symmetrical) adjacency matrix, mat:

              Acousmatic Acoustic Afro-beat Alternative Ambient
  Acousmatic         125       11         3           3       1
  Acoustic            11   112398      1810       24216    3824
  Afro-beat            3     1810     10386        1220     298
  Alternative          3    24216      1220      103286    2838
  Ambient              1     3824       298        2838   20400

As an example, I want to transform the value of "Alternative-Acoustic" (24216) by finding the maximum value for "Acoustic" given by its diagonal (112398) and the maximum value for "Alternative" given by its diagonal (103286), and by dividing "Alternative-Acoustic" (24216) by the lesser of those two numbers. So in this case, the lesser would be "Alternative," so I want to transform the "Alternative-Acoustic" value with 24216/103286=~.2345.

I want to automatically perform this transformation for all values in this matrix, which would result in a matrix with values ranging from 0-1 with the diagonals as all 1's.

I tried the following in many different iterations with "mat" as both a matrix and a data frame, but I do not know how to correctly query the row and column maximums for each value in the matrix. This is using nonexistent functions ('colmax' and 'rowmax'), but I think it most clearly expresses what I want to do:

transformedmat <- apply(mat,1:2, function(x) x/min(colmax(x),rowmax(x)))

I also tried to write an embedded function, but that ended poorly, and I'm wondering if there's a simpler solution:

rescalemat <- function(mat){
    apply(mat, 1, function(x){
    colmax<-apply(mat, 2, function(x) max(x))
    rowmax<-apply(mat, 1, function(x) max(x))
    x/min(colmax,rowmax)
    mat
})
}

Any help would be greatly appreciated.

Thanks.

like image 260
Mon Avatar asked Mar 04 '14 21:03

Mon


People also ask

How do I find the maximum value of each row in R?

If we want to find the maximum of values two or more columns for each row in an R data frame then pmax function can be used.

How do you get the max of each column in R?

For example, if we have a matrix M that contains 2 rows and 2 columns with values 1, 2 in the first row and 3, 4 in the second row then the maximum for each of the columns in that matrix can be found by using the syntax; apply(M,2,max), hence the result will be 3, 4.

How do you divide a matrix by a number in R?

R Matrix Division To divide elements of a matrix with the corresponding elements of other matrix, use division (/) operator. The multiplication happens only between the (i,j) of first matrix and (i,j) of second matrix.

How do I divide multiple columns by a number in R?

To divide each column by a particular column, we can use division sign (/). For example, if we have a data frame called df that contains three columns say x, y, and z then we can divide all the columns by column z using the command df/df[,3].


2 Answers

try this:

A1 = mat/apply(mat,1,max)
A2 = t(t(mat)/apply(mat,2,max))
result = ifelse(A1>A2,A1,A2)
like image 75
amit Avatar answered Nov 16 '22 01:11

amit


Unless I've missed something, this approach looks valid too:

res = diag(mat)
#names(res) = colnames(mat)       
mat / outer(res, res, pmin) 

#            Acousmatic  Acoustic  Afro.beat Alternative    Ambient
#Acousmatic       1.000 0.0880000 0.02400000   0.0240000 0.00800000
#Acoustic         0.088 1.0000000 0.17427306   0.2344558 0.18745098
#Afro-beat        0.024 0.1742731 1.00000000   0.1174658 0.02869247
#Alternative      0.024 0.2344558 0.11746582   1.0000000 0.13911765
#Ambient          0.008 0.1874510 0.02869247   0.1391176 1.00000000

Where mat is:

mat = structure(c(125L, 11L, 3L, 3L, 1L, 11L, 112398L, 1810L, 24216L, 
3824L, 3L, 1810L, 10386L, 1220L, 298L, 3L, 24216L, 1220L, 103286L, 
2838L, 1L, 3824L, 298L, 2838L, 20400L), .Dim = c(5L, 5L), .Dimnames = list(
    c("Acousmatic", "Acoustic", "Afro-beat", "Alternative", "Ambient"
    ), c("Acousmatic", "Acoustic", "Afro.beat", "Alternative", 
    "Ambient")))
like image 29
alexis_laz Avatar answered Nov 15 '22 23:11

alexis_laz