【问题标题】:Finding minimum value for each row from 2 matrix R从2个矩阵R中找到每一行的最小值
【发布时间】:2018-12-25 03:19:37
【问题描述】:

我需要 2 个矩阵中每一行的最小值。行名称在两个矩阵中都很常见,但列名称会发生​​变化。

例如:

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)))

预期结果:

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

我试过了

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

但不知道如何从矩阵和列表中分别找到最小值作为预期的输出文件。我也有重复的行名和列名。

【问题讨论】:

  • 在使用基于随机数的样本数据时,请始终使用固定种子(例如set.seed(1234))以确保预期输出的可重复性。否则无法重现您的预期输出。

标签: r matrix


【解决方案1】:

这是tidyverse 的可能性。请注意,我使用固定种子set.seed(2017) 来生成样本数据。

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

样本数据

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)))

更新

针对您的评论,要保留前 3 个最低条目,您可以使用 top_n(如 @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

【讨论】:

  • 您好 Maurits,谢谢!我重复了行名和列名,但我不想制作唯一列表。如何保留重复的行名和列名并仍然实现此输出?
  • @amarPar 我不确定你的意思。请更新您的帖子以包含更具代表性的示例数据集和预期输出(请记住使用固定种子)。
  • 您也可以使用top_n(-1,"Minimum") 代替您的filter 电话
  • @Moody_Mudskipper 这很好;我从来没有意识到top_n 可以接受第三个参数。谢谢你:-)
  • 嗨,是否也可以保留第一个、第二个和第三个最小值的结果。如果 2 个或多个不同的 ID 获得相同的值并满足第一个、第二个或第三个最低标准,我宁愿保留所有。谢谢。
【解决方案2】:

使用来自@Maurits 的样本数据,以 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

【讨论】:

  • 喜穆迪,谢谢,我收到错误,data.frame(最小值,id = colnames(XY)[wm_])data.frame 中的错误(最小值,id = colnames(XY)[wm_] ) : 参数暗示不同的行数:10、4。
  • 用你的真实数据,而不是样本数据,对吧?
  • 这真的很奇怪,这些都是非常简单和稳定的功能,它在我这边工作得很好,请仔细检查你从@Maurits 的帖子中复制它是否正确并且你没有覆盖@987654322 @ 或 wm_,如果仍然失败,请告诉我 length(Minimum)length(colnames(XY)[wm_])) 是什么
  • 是的,我直接从 Maurit 的帖子中复制。 > 长度(最小值)[1] 40 > 长度(列名(XY)[wm_])[1] 4
【解决方案3】:

您可以将您的矩阵与cbind 组合并与t() 进行转置。然后来自dplyrsummarise_all 可以为每一行提供一个分钟。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-11-29
    • 2020-10-11
    • 1970-01-01
    • 2019-04-25
    • 1970-01-01
    • 2020-05-09
    • 2013-02-25
    相关资源
    最近更新 更多