2个矩阵R中每行的唯一最小值

时间:2018-08-13 09:37:25

标签: r

我有2个具有相同行名的矩阵,我发现了每行的前3个最小值(由于@ Maurits Evers)。现在,我需要找到3个最小值,但不要重复使用同名字符。我在计算最小值时需要唯一的ID,例如,如果Inst1选择Alt5作为最小值,则下一行(Inst2)不应选择相同的ID。因此,如果应该至少选择它们之前,我应该跳过,并寻找下一个最小值并报告它们。但是,如果第二行的最小值小于第一行的最小值,则第一行将替换为该特定行的下一个最小值。有什么建议吗?

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

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

#Expected output:
 Inst Min1 1 Min2 2 Min3 3
 Inst1 Ref4  0.0251 Alt2  0.228 Ref5 0.395375 
 Inst2 Alt5  0.110 Alt4  0.212 Alt1 0.380 
 Inst4 Ref3  0.00202 Alt3  0.0175 Ref1  0.289

1 个答案:

答案 0 :(得分:0)

感谢您的提问和评论。有点僵硬的前向解决方案:让循环选择之前不存在的最小值,并记录先前选择的最小值以定义哪个是给定ID的最小值。对于格式化可以使用扩展功能

      mindata <-as.data.frame(cbind.data.frame(X, Y) %>%
      rownames_to_column("row") %>%
      gather(Id, Minimum, -row) %>%
      arrange(row, Minimum))

Pr_min <- c()
Def_min <- c()
par<-sum(mindata$row=="Inst1")
i<-1

  for (row in unique(mindata$row)){
    initial3 <- head(mindata[mindata$row==row & !(mindata$Id %in% Pr_min$Id), c(1:3) ], 3)
   if(nrow(initial3)==0){next} 
    New_min <-mindata[(1 +(i-1)*par):max(rownames(initial3)), 2:3]

    Pr_min <- rbind(Pr_min, initial3)
    Def_min <- rbind(Def_min, New_min)
    i <- i+1
  }

  Final <- Pr_min %>%
  left_join((Def_min%>%
  group_by(Id)%>%
  summarise(min=min(Minimum))), by="Id")%>%
  select(-Minimum)

CN <- rep(c("Min1", "Min2", "Min3"), ceiling(length(Final$Id)/3))[1:nrow(Final)]
Val_min <-Final%>% cbind( CN) %>% select(-Id)%>% spread(CN, min)
name_min <-Final%>% cbind( CN ) %>% select(-min)%>% spread(CN, Id)
cbind(name_min,Val_min[, 2:4])