2016-11-03 8 views
1

Ich habe eine Tabelle, die eine Menge von Messungen von verschiedenen Metern enthält. Jede Messung wird in einer neuen Zeile gespeichert und hat den aktuellen Meterwert. Ich muss den Unterschied zwischen jeder aufeinanderfolgenden Messung pro Meter unterscheiden.Berechnen Delta zwischen verschiedenen Zeilen in der gleichen Tabelle

Simplified imput:

[2016-11-03,MeterA,45] 
[2016-11-03,MeterB,45] 
[2016-11-04,MeterA,47] 
[2016-11-04,MeterB,54] 

Derzeit ich dies für Schleifen mit mehreren mache aber das dauert lange und es wahrscheinlich ist eine effizientere Art und Weise. Code zur Zeit

data$diff <- 0; 
for(address in unique(data$Address)){ 
    subaddr <- subset(data, data$Address== address) 
    for(meter in unique(subaddr$Meter)){ 
     submeter <- subset(subaddr, subaddr$Meter == meter) 
     for (i in 1:nrow(submeter)){ 
      if(i > 1){ 
       prow = submeter[i-1,] 
       row = submeter[i,] 
       data[which(data$Address == address & data$Meter == meter & data$UCPTlogTime == row$UCPTlogTime),]$diff <- row$UCPTvalue - prow$UCPTvalue 
      }  
      } 
    } 
} 

Ausgang Wunsch

[2016-11-03,MeterA,0] 
[2016-11-03,MeterB,0] 
[2016-11-04,MeterA,2] 
[2016-11-04,MeterB,9] 
+0

Verwendung 'lag' von dplyr. – yeedle

Antwort

1

Dies ist ein Kinderspiel mit dplyr mit der lag Funktion. Unter der Annahme, die Spalten in Ihrem Datenrahmen sind UCPTlogTime, genannt Address, Meter und UCPTvalue:

library(dplyr) 

data <- data %>% group_by(Address, Meter) %>% 
    mutate(delta = order_by(UCPTlogTime, UCPTvalue - lag(UCPTvalue))) %>% 
    mutate(delta = ifelse(is.na(delta), 0, delta)) 
+0

Danke!, Zuerst dauerte es über 4 Minuten, um 65k Zeilen zu machen, jetzt eine Frage von Sekunden !. – fathomson

+0

Der beste Rat, den ich je bekommen habe: In R, wenn du es mit einer Schleife machst, machst du es wahrscheinlich falsch. – yeedle

1

Dies scheint einfacher, wo diff ist, was Sie berechnen wollte.

for (i in 1:nrow(t)){t$diff[i]<-t[i,3]-t[1,3]} 
t 
    v1  v2 v3 diff 
1 Date1 MeterA 45 0 
2 Date2 MeterB 45 0 
3 Date3 MeterC 47 2 
4 Date4 MeterD 54 9 
2

Hier ist ein Ansatz mit data.table:

library(data.table) 
dt <- data.table(df) 

dt[,delta := c(0, diff(value)), by = "group"][] 
#   date group value delta 
# 1: 2016-11-04  A 24  0 
# 2: 2016-11-04  B 24  0 
# 3: 2016-11-05  A 30  6 
# 4: 2016-11-05  B 31  7 
# 5: 2016-11-06  A 36  6 
# 6: 2016-11-06  B 38  7 
# 7: 2016-11-07  A 44  8 
# 8: 2016-11-07  B 46  8 
# 9: 2016-11-08  A 51  7 
# 10: 2016-11-08  B 54  8 
# 11: 2016-11-09  A 57  6 
# 12: 2016-11-09  B 56  2 
# 13: 2016-11-10  A 61  4 
# 14: 2016-11-10  B 61  5 
# 15: 2016-11-11  A 68  7 
# 16: 2016-11-11  B 69  8 
# 17: 2016-11-12  A 72  4 
# 18: 2016-11-12  B 73  4 
# 19: 2016-11-13  A 81  9 
# 20: 2016-11-13  B 82  9 

df <- data.frame(
    date = rep(Sys.Date() + 1:10, each = 2), 
    group = rep(c("A", "B"), 10), 
    value = rpois(2, 20) + cumsum(rpois(20, 3)), 
    stringsAsFactors = FALSE 
) 
1

Hier ist ein weiterer Ansatz ist dplyr mit - nicht eine Variable für Address sehen, aber man konnte das zum group_by()

hinzufügen
library(dplyr) 

df <- data.frame(read_date = c("2016-11-03", 
           "2016-11-03", 
           "2016-11-04", 
           "2016-11-04"), 
       Meter = c("MeterA", 
          "MeterB", 
          "MeterA", 
          "MeterB"), 
       UCPTvalue = c(45, 
           45, 
           47, 
           54)) 

out <- df %>% 
     group_by(Meter) %>% 
     mutate(diff = ifelse(row_number() == 1, 
          0, 
          UCPTvalue - lag(UCPTvalue, 1))) 
Verwandte Themen