2015-11-24 5 views
7

Desidero restituire una nuova colonna in un file data.table che mostri il numero di righe in basso fino a quando non viene raggiunto un valore inferiore al valore corrente (di Temp).R righe di conteggio dati.table fino al raggiungimento del valore

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

Questo è quanto vorrei farlo sembrare:

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

risposta

2

Ecco un metodo dplyr:

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 che è grande @jeremycg, e per rendere sicuro di aver capito bene se volevo controllare che riga il valore Temp è andato inferiore a una colonna alternativa (colonna aggiuntiva) valore come cambierebbe questo metodo? Grazie – user3740289

+0

Nessun problema. Si cambierebbe '. $ Temp [x: length (. $ Temp)] a'. $ Additionalcolumn [x: length (. $ Temp)] '. – jeremycg

+1

Purtroppo questo (e la mia risposta cancellata) sembrano essere lenti come una settimana bagnata. Anche su 100K casi, questo sta prendendo un minuto più. Penso che ci debba essere un modo per aggirare questo attraverso alcuni join o qualcosa di difficile. Arun, dove sei ?! – thelatemail

1

Questo fa il lavoro - non molto veloce anche se

DT[, rowN := .I] 

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

Utilizzo della nuova implementazione n on-equi unisce nella versione di sviluppo attuale, questo può essere realizzato in modo semplice come segue:

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 

Il numero di riga è necessaria poiché occorre trovare indici inferiori l'indice corrente, quindi deve essere una condizione nel join. Eseguiamo un auto join , ad esempio per ogni riga in DT (interna), in base alle condizioni fornite all'argomento on, troviamo il primo indice di riga corrispondente in DT (esterno). Quindi sottraiamo gli indici di riga per ottenere la posizione dalla riga corrente. x.row si riferisce all'indice esterno DT e i.row al numero interno DT.

Per ottenere la versione di sviluppo, consultare le istruzioni di installazione here.


sulle righe 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