2014-12-12 15 views
5

Jeśli istnieje przykładowy zestaw danych, jak poniżej.przy użyciu funkcji lapply w data.table w 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 

Chcę wybrać dwie najniższe liczby i chcę zmienić wartość 0 na inne numery.

jak

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 

myślę, że kodowanie jest

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

ale zmienia wszystko 0

Jak mogę rozwiązać ten problem.

+0

Co jeśli liczby nie są wyjątkowe? To znaczy. załóżmy, że masz '> 2' 1s w pierwszej kolumnie, w takim przypadku, czy chcesz uzyskać' pierwszy' dwa 1s? – akrun

+0

IIUC chciałbyś zamienić wszystkie oprócz dwóch najniższych wartości dla * każdej kolumny * na 0. Zrobiłbym to z pętlą for przez kolumny i używając 'sort.int' wraz z argumentem' partial' by znaleźć nth najmniejsza dla każdej kolumny i zastępująca wszystkie pozostałe wiersze wartością 0 dla tej kolumny. Ale możemy to zrobić bardziej efektywnie, stosując algorytmy czasu liniowego, aby znaleźć n-ty maksimum (które jest [FR # 919] (http://github.com/Rdatatable/data.table/issues/919), jeszcze do zrobienia). – Arun

Odpowiedz

0

Może można spróbować

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

Aby rozwinąć na mój komentarz, chciałbym zrobić coś takiego:

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

Ten obwodów nad wszystkich kolumn w tmp i dostaje 2nd minimalna wartość dla każdej kolumny przy użyciu argumentu sort.int z argumentem partial, który jest nieco bardziej wydajny niż użycie sort (ponieważ nie musimy sortować całego zestawu danych, aby znaleźć 2. minimalną wartość).

Następnie używamy set() zastąpić te wiersze, w których wartość kolumny jest większa niż 2 wartości minimalnej, za tym kolumny z wartością 0.

Powiązane problemy