2015-11-24 12 views
7

Ich möchte eine neue Spalte in einer data.table zurückgeben, die angibt, wie viele Zeilen abwärts liegen, bis ein Wert unter dem aktuellen Wert (von Temp) erreicht wird.R data.table Anzahl der Zeilen, bis der Wert erreicht ist

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

Dies ist, wie ich es betrachten möchte:

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

Antwort

2

hier eine dplyr Methode:

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, das große @jeremycg ist, und um sicherzustellen, dass ich es richtig verstehe, wenn ich zu überprüfen, was der Temp Wert ging niedriger als eine alternative Säule (zusätzliche Spalte Zeile gesucht) Wert, wie würde sich diese Methode ändern? Danke – user3740289

+0

Kein Problem. Sie würden die '. $ Temp [x: length (. $ Temp)]' in '. $ Additionalcolumn [x: length (. $ Temp)]' ändern. – jeremycg

+1

Leider scheint diese (und meine eigene gelöschte Antwort) so langsam zu sein wie eine nasse Woche. Sogar bei 100K Fällen dauert dies eine Minute plus. Ich denke, dass es einen Weg geben muss, um dies durch einige Verbindungen oder etwas schwierig zu umgehen. Arun, wo bist du ?! – thelatemail

1

Dies hat den Zweck erfüllt - nicht sehr schnell, obwohl

DT[, rowN := .I] 

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

Verwendung der neu implementierten n on-equi in der aktuellen Entwicklungsversion beitritt, kann dies wie folgt auf einfache Art und Weise erreicht werden:

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 

Die Zeilennummer ist notwendig, da wir Indizes niedriger als der aktuelle Index finden müssen, muss daher eine sein Bedingung in der Verknüpfung. Wir führen einen Self-Join durch, d. H. Für jede Zeile in (inner), basierend auf dem Argument on Argument finden wir den ersten übereinstimmenden Zeilenindex in DT (außen). Dann subtrahieren wir die Zeilenindizes, um die Position von der aktuellen Zeile zu erhalten. x.row bezieht sich auf den Index der äußeren DT und i.row auf die innere DT.

Die Entwicklungsversion finden Sie in den Installationsanweisungen here.


Auf 1e5 Reihen:

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 
Verwandte Themen