简体   繁体   中英

Finding minimum value for each row from 2 matrix R

I need the minimum value for each rows from 2 matrix. The row names are common in both matrix but the column name changes.

eg:

matrix 1:
X <- matrix(runif(20), nrow=4)
rownames(X) <- paste0("Inst", seq(nrow(X)))
colnames(X) <- paste0("Ref", seq(ncol(X)))

matrix 2:
Y <- matrix(runif(20), nrow=4)
rownames(Y) <- paste0("Inst", seq(nrow(X)))
colnames(Y) <- paste0("Alt", seq(ncol(X)))

Expected result:

             Minimum    Id
    Inst1   0.1275317  Ref15
    Inst2   0.0006247  Alt4
    Inst3   0.04583117 Ref13
    Inst4   0.1111354  Alt5

I tried

t(apply(Y, 1, sort)[ 1, ]) 
t(apply(X, 1, sort)[ 1, ])

Yet don't know how to find the minimum from both matrix and tabulate separately as expected output file. Also I have duplicated rownames and colnames.

Here is a tidyverse possibility. Note that I've used the fixed seed set.seed(2017) for the generation of sample data.

library(tidyverse)
cbind.data.frame(X, Y) %>%
    rownames_to_column("row") %>%
    gather(Id, Minimum, -row) %>%
    group_by(row) %>%
    filter(Minimum == min(Minimum)) %>%
    arrange(row)
## A tibble: 4 x 3
## Groups:   row [4]
#  row   Id    Minimum
#  <chr> <chr>   <dbl>
#1 Inst1 Ref4  0.0251
#2 Inst2 Alt5  0.110
#3 Inst3 Ref2  0.0393
#4 Inst4 Ref3  0.00202

Sample data

set.seed(2017)
X <- matrix(runif(20), nrow=4)
rownames(X) <- paste0("Inst", seq(nrow(X)))
colnames(X) <- paste0("Ref", seq(ncol(X)))

Y <- matrix(runif(20), nrow=4)
rownames(Y) <- paste0("Inst", seq(nrow(Y)))
colnames(Y) <- paste0("Alt", seq(ncol(Y)))

Update

In response to your comment, to retain the top 3 lowest entries you can use top_n (as suggested by @Moody_Mudskipper)

cbind.data.frame(X, Y) %>%
    rownames_to_column("row") %>%
    gather(Id, Minimum, -row) %>%
    group_by(row) %>%
    top_n(-3, Minimum) %>%
    arrange(row, Minimum)
## A tibble: 12 x 3
## Groups:   row [4]
#   row   Id    Minimum
#   <chr> <chr>   <dbl>
# 1 Inst1 Ref4  0.0251
# 2 Inst1 Alt3  0.0763
# 3 Inst1 Alt5  0.129
# 4 Inst2 Alt5  0.110
# 5 Inst2 Alt4  0.212
# 6 Inst2 Alt3  0.261
# 7 Inst3 Ref2  0.0393
# 8 Inst3 Alt5  0.177
# 9 Inst3 Ref1  0.469
#10 Inst4 Ref3  0.00202
#11 Inst4 Alt3  0.0175
#12 Inst4 Ref1  0.289

You can combine your matrix with cbind and transpose it with t() . Then a summarise_all from dplyr could give you a min for each row.

library(dplyr)
as.data.frame(t(cbind(X,Y))) %>% summarise_all(funs(min))
#        Inst1       Inst2       Inst3      Inst4
# 1 0.05845904 0.006901952 0.009513836 0.05197972

Using sample data from @Maurits, in base R :

XY <- cbind(X,Y)
wm_     <- apply(XY,1,which.min)
Minimum <- apply(XY,1,min)
data.frame(Minimum, id = colnames(XY)[wm_])
#           Minimum   id
# Inst1 0.025093514 Ref4
# Inst2 0.110404957 Alt5
# Inst3 0.039322336 Ref2
# Inst4 0.002020766 Ref3

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM