2015-11-24 14 views
7

Chciałbym zwrócić nową kolumnę w data.table, która pokazuje, ile wierszy w dół, aż zostanie osiągnięta wartość niższa niż bieżąca wartość (Temp).R data.table zliczanie wierszy do momentu osiągnięcia wartości

library(data.table) 
set.seed(123) 
DT <- data.table(Temp = runif(10,0,20)) 

ten sposób chciałbym go szukać:

set.seed(123) 
DT <- data.table(
     Temp = runif(10,0,20), 
     Day_Below_Temp = c("5","1","3","2","1","NA","3","1","1","NA") 
) 

Odpowiedz

2

Oto dplyr metoda:

library(dplyr) 
set.seed(123) 
dt <- data.frame(Temp = runif(10,0,20)) 
dt %>% mutate(Day_Below_Temp = 
       sapply(1:length(Temp), function(x) min(which(.$Temp[x:length(.$Temp)] < .$Temp[x]))-1)) 

     Temp Day_Below_Temp 
1 5.751550    5 
2 15.766103    1 
3 8.179538    3 
4 17.660348    2 
5 18.809346    1 
6 0.911130   Inf 
7 10.562110    3 
8 17.848381    1 
9 11.028700    1 
10 9.132295   Inf 
+0

Ok to świetnie @jeremycg, i upewnić się, że rozumieją to dobrze, jeśli chciałem sprawdzić co row wartość Temp poszedł niższa niż kolumny alternatywnego (dodatkowa kolumna) wartość, w jaki sposób zmieni się ta metoda? Dziękuję – user3740289

+0

Bez problemu. Zmienisz wartość '. $ Temp [x: length (. $ Temp)] na'. $ Additionalcolumn [x: length (. $ Temp)] '. – jeremycg

+1

Niestety ta (i moja własna usunięta odpowiedź) wydaje się być równie powolna jak mokry tydzień. Nawet w przypadku 100 000 zajmuje to chwilę. Myślę, że musi istnieć sposób obejścia tego poprzez niektóre sprzężenia lub coś podstępnego. Arun, gdzie jesteś ?! – thelatemail

1

ta spełnia swoje zadanie - nie bardzo szybko, chociaż

DT[, rowN := .I] 

DT[, Day_Below_Temp := which(DT$Temp[rowN:nrow(DT)] < Temp)[1] - 1, 
    by = rowN 
    ][, rowN := NULL] 
4

Korzystanie z nowo wdrożonego n na equi przyłącza się do aktualnej wersji rozwojowej, można to osiągnąć w prosty sposób, jak następuje:

require(data.table) # v1.9.7+ 
DT[, row := .I] # add row numbers 
DT[DT, x.row-i.row, on = .(row > row, Temp < Temp), mult="first"] 
# [1] 5 1 3 2 1 NA 3 1 1 NA 

Numer wiersza jest konieczne, ponieważ musimy znaleźć wskaźniki niższe niż bieżący indeks, stąd musi być stan w złączeniu. Wykonujemy samołączenie , tj. Dla każdego wiersza w DT (wewnętrznym), w oparciu o warunek dostarczony do argumentu on, znajdujemy pierwszy zgodny indeks wiersza w DT (zewnętrzny). Następnie odejmujemy indeksy wierszy, aby uzyskać pozycję z bieżącego wiersza. x.row odnosi się do indeksu zewnętrznego DT i i.row do wewnętrznego DT.

Aby uzyskać wersję devel, patrz instrukcja instalacji here.


Na rzędach 1E5:

set.seed(123) 
DT <- data.table(Temp = runif(1e5L, 0L, 20L)) 

DT[, row := .I] 
system.time({ 
    ans = DT[DT, x.row-i.row, on = .(row > row, Temp < Temp), mult="first", verbose=TRUE] 
}) 
# Non-equi join operators detected ... 
# forder took ... 0.001 secs 
# Generating non-equi group ids ... done in 0.452 secs 
# Recomputing forder with non-equi ids ... done in 0.001 secs 
# Found 623 non-equi group(s) ... 
# Starting bmerge ...done in 8.118 secs 
# Detected that j uses these columns: x.row,i.row 
# user system elapsed 
# 8.492 0.038 8.577 

head(ans) 
# [1] 5 1 3 2 1 12 
tail(ans) 
# [1] 2 1 1 2 1 NA