2014-12-12 9 views
5

Se è presente un set di dati di esempio come indicato di seguito.utilizzando la funzione in lapply in data.table in r

> tmp <- data.table(x=c(1:10),y=(5:14)) 
> tmp 
    x y 
1: 1 5 
2: 2 6 
3: 3 7 
4: 4 8 
5: 5 9 
6: 6 10 
7: 7 11 
8: 8 12 
9: 9 13 
10: 10 14 

Voglio scegliere il numero più basso e voglio cambiare il valore 0 con gli altri numeri.

come

x y 
1: 1 5 
2: 2 6 
3: 0 0 
4: 0 0 
5: 0 0 
6: 0 0 
7: 0 0 
8: 0 0 
9: 0 0 
10: 0 0 

Penso che la codifica è

tmp[, c("x","y"):=lapply(.SD, x[which(!x %in% sort(x)[1:2])] = 0}), .SDcols=c("x","y")] 

ma cambia tutto 0

Come posso risolvere questo problema.

+0

E se i numeri non sono unici? Vale a dire. supponiamo di avere '> 2' 1s nella prima colonna, in tal caso, vuoi ottenere i' primi 'due 1? – akrun

+0

IIUC si desidera sostituire tutti i valori 2 tranne il più basso per * ogni colonna * su 0. Lo farei con for-loop sulle colonne e usare 'sort.int' insieme all'argomento' partial' per trovare l'ennesimo più piccolo per ogni colonna e sostituisce tutte le altre righe a 0 per quella colonna. Ma possiamo farlo in modo più efficiente implementando algoritmi di tempo lineare per trovare l'ennesimo massimo (che è [FR # 919] (http://github.com/Rdatatable/data.table/issues/919), ancora da fare). – Arun

risposta

0

Può essere che si può provare

tmp[, lapply(.SD, function(x) replace(x, 
      !rank(x, ties.method='first') %in% 1:2, 0))] 
# x y 
#1: 1 5 
#2: 2 6 
#3: 0 0 
#4: 0 0 
#5: 0 0 
#6: 0 0 
#7: 0 0 
#8: 0 0 
#9: 0 0 
#10:0 0 
4

Per espandere il mio commento, mi piacerebbe fare qualcosa di simile:

for (j in names(tmp)) { 
    col = tmp[[j]] 
    min_2 = sort.int(unique(col), partial=2L)[2L] # 2nd lowest value 
    set(tmp, i = which(col > min_2), j = j, value = 0L) 
} 

Questo loop su tutte le colonne in tmp, e ottiene il 2 ° valore minimo per ogni colonna utilizzando sort.int con argomento partial, che è leggermente più efficiente rispetto all'utilizzo di sort (in quanto non è necessario ordinare l'intero set di dati per trovare il 2 ° valore minimo).

Poi usiamo set() per sostituire le righe in cui il valore della colonna è maggiore del valore minimo di 2 °, per che colonna, con il valore 0.