Save the two highest values ββof each row in the list of matrices r
Suppose I have a list of matrices:
$`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 Code for creating matrices:
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 I want to keep the two highest values ββin each row and replace the remaining smaller values ββof the other cells in the same row with 0.
If there are more than two cells with the highest value, I want to leave all these cells as they are (for example: 10 10 10 0-> 10 10 10 0, 5 1 9 5 β 5 0 9 5). All other cells in the row should be set to 0 again.
The results should look like this:
$`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 I'm not sure how to approach this problem, so any help is appreciated!
Here is one approach:
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 This works by iterating over the elements of the list (with lapply ), treating each one in turn as an object x , and then iterating over the lines of that x (with apply(x, 1, ...) ), calling the string y and applying a function to it.
Function applied to string y of list item x :
function(y) { y[y < tail(sort(y), 2)] <- 0 y } which identifies the two highest elements of the string ( tail(sort(y), 2) ), returns a logical vector indicating which of the y elements are not in this set (with y < ... ), multiplies the vector y elements with this logical vector and assigns these elements 0 . Finally, it returns the changed y .