2015-03-03 13 views
5

Supponiamo che io sono un elenco di matrici:Mantenere i 2 più alti valori di ogni riga in un elenco di matrici 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 

codice per creare le matrici:

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 

voglio mantenere la due valori più alti in ogni riga e sostituiscono i restanti valori più piccoli delle altre celle nella stessa riga con gli 0.

Se ci sono più di due celle con il valore più alto, voglio lasciare tutte quelle celle così come sono (ad esempio: 10 10 10 0> 10 10 10 0, 5 1 9 5 -> 5 0 9 5). Tutte le altre celle della riga devono essere nuovamente impostate su 0.

Il risultato dovrebbe essere simile a questo:

$`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 

Non sono sicuro di come affrontare questo problema, quindi ogni aiuto è altamente benvenuto!

risposta

4

Ecco uno approccio:

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 

Questo funziona mediante iterazione sugli elementi della lista (con lapply), trattando a turno come oggetto x, e l'iterazione poi sulle righe di tale x (con apply(x, 1, ...)) chiamando la riga e applicandogli una funzione.

La funzione applicata alla fila y dell'elenco elemento x è:

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

che identifica i due elementi di maggior valore della riga (tail(sort(y), 2)), restituisce un vettore logico indicante che gli elementi di y non sono in quel set (con y < ...), sottopone gli elementi del vettore a quel vettore logico e assegna 0 a questi elementi. Alla fine restituisce lo modificato.

+2

Forse usare 'y <' come sarà più veloce di '% in%'? Inoltre, è probabile che funzioni meglio con i numeri in virgola mobile. +1. – BrodieG

+0

@BrodieG Buon punto! Grazie. – jbaums

Problemi correlati