将每行的 2 个最大值保留在矩阵列表 r 中

Keep the 2 highest values of each row in a list of matrices r

假设我有一个矩阵列表:

$`2010`
   1  2  3 4
1  0  3  5 6
2  5  1  9 5
3  0  0  0 0
4 10 10 10 0

$`2011`
  1 2 3 4
1 0 2 3 6
2 5 0 3 1
3 2 4 0 1
4 2 1 2 1

创建矩阵的代码:

cntry<-c(1,2,3,4)
a<-c(0,5,0,10)
b<-c(3,1,0,10)
c<-c(5,9,0,10)
d<-c(6,5,0,0)
k<-data.frame(a,b,c,d)
k<-as.matrix(k)
dimnames(k)<-list(cntry,cntry)

e<-c(0,5,2,2)
f<-c(2,0,4,1)
g<-c(3,3,0,2)
h<-c(6,1,1,1)
l<-data.frame(e,f,g,h)
l<-as.matrix(l)
dimnames(l)<-list(cntry,cntry)

list<-list(k,l)
names(list)<-2010:2011

我想保留每行中的两个最大值,并将同一行中其他单元格中剩余的较小值替换为 0。

如果有两个以上的单元格具有最高值,我想保留所有这些单元格的原样(例如:10 10 10 0-> 10 10 10 0, 5 1 9 5 -> 5 0 9 5).该行的所有其他单元格应再次设置为 0。

结果应如下所示:

$`2010`
   1  2  3 4
1  0  0  5 6
2  5  0  9 5
3  0  0  0 0
4 10 10 10 0

$`2011`
  1 2 3 4
1 0 0 3 6
2 5 0 3 0
3 2 4 0 0
4 2 0 2 0

我不确定如何解决这个问题,所以非常欢迎任何帮助!

这是一种方法:

lapply(list, function(x) {
  t(apply(x, 1, function(y) {
    y[!y %in% tail(sort(y), 2)] <- 0
    y
  }))
})

## $`2010`
##    1  2  3 4
## 1  0  0  5 6
## 2  5  0  9 5
## 3  0  0  0 0
## 4 10 10 10 0
## 
## $`2011`
##   1 2 3 4
## 1 0 0 3 6
## 2 5 0 3 0
## 3 2 4 0 0
## 4 2 0 2 0

这是通过迭代列表的元素(使用 lapply),依次将每个元素视为对象 x,然后迭代 x 的行(使用 apply(x, 1, ...)) 调用行 y 并对其应用函数。

应用于列表元素 x 的行 y 的函数是:

function(y) {
  y[y < tail(sort(y), 2)] <- 0
  y
}

标识该行的两个最高值元素 (tail(sort(y), 2)),returns 一个逻辑向量,指示 y 的哪些元素不在该集合中(与y < ...),使用该逻辑向量对向量 y 的元素进行子集化,并将 0 分配给这些元素。最后,它 returns 修改了 y.