Jdj67
Jdj67

Reputation: 65

Output row index of first element of every column in a matrix to satisfy a logical condition

I have a large matrix (8,000 x 8,000) containing numerical data. I would like an output matrix with a single row containing the row index of the first element in each column to satisfy a logical operator. Note that not all the columns will have an element satisfying the condition.

Example input:

    Column
Row   1         2          3          4          
 1  34.349    23.642     64.321     12.320      
 2  74.734    11.755     29.424     55.432     
 3  31.345    99.328     64.236     45.453     
 4  22.436    84.345     45.323     21.008     
 5  7.323    101.324     45.254     32.233      
 6  119.345  23.324      72.474     53.543

Logical operator: x > 70 gives an example output of:

    Column
Row   1         2          3          4
 1    2         3          6          NA

I'm new to R and struggled to get this output using the standard match and which functions.

Upvotes: 1

Views: 150

Answers (1)

Ronak Shah
Ronak Shah

Reputation: 388907

Since, it is a matrix we can use apply with margin = 2 (column-wise). Here we check if the column has at least one value greater than 70 and return it's index or else return NA.

apply(mat > 70, 2, function(x) if (any(x)) which.max(x) else NA)

#V1 V2 V3 V4 
# 2  3  6 NA 

Ideally apply(mat > 70, 2, which.max) , would have given you what you need but it fails when you have no element greater than 70 hence, the check with if and any condition.

This would also work with dataframe.


In case there are no elements greater than 70 and column has NA values, it returns an error.

mat[1, 4] <- NA
apply(mat > 70, 2, function(x) if (any(x)) which.max(x) else NA)

Error in if (any(x)) which.max(x) else NA : missing value where TRUE/FALSE needed

In such case, we can use na.rm argument in any to avoid this error.

apply(mat > 70, 2, function(x) if (any(x, na.rm = TRUE)) which.max(x) else NA)

#V1 V2 V3 V4 
# 2  3  6 NA 

Upvotes: 1

Related Questions