2016-07-26 10 views
1

wie ich mein Problem mit PHP/MySQL oder Excel aufgrund der Datengröße nicht lösen konnte, versuche ich, meine ersten Schritte mit R jetzt und ein wenig zu kämpfen. Das Problem ist folgendes: Ich habe einen zweiten Neben zweite CSV-Datei mit einem halben Jahr von Daten, sieht das wie folgt aus:R: Find fehlende Zeitstempel in csv

metering,timestamp 
123,2016-01-01 00:00:00 
345,2016-01-01 00:00:01 
243,2016-01-01 00:00:02 
101,2016-01-01 00:00:04 
134,2016-01-01 00:00:06 

Wie Sie sehen, gibt es einige Sekunden jeder einmal in eine Weile fehlen (Frag mich nicht, warum die Werte vor dem Zeitstempel geschrieben sind, aber so habe ich die Daten erhalten ...). Jetzt versuche ich die Anzahl der fehlenden Werte (= Sekunden) zu berechnen.

So war meine Idee

  1. einen Vektor zu erstellen, die korrekt ist (beinhaltet alle sec-by-sec-Zeitstempel),
  2. erfüllen die CSV mit diesem neuen Vektor-Datei, und
  3. Summe up alle Zeitstempel ohne Wert.

konnte ich Schritt 1 passieren mit dem folgenden Code machen:

RegularTimeSeries <- seq(as.POSIXct("2016-01-01 00:00:00", tz = "UTC"), as.POSIXct("2016-01-01 00:00:30", tz = "UTC"), by = "1 sec") 
write.csv(RegularTimeSeries, file = "RegularTimeSeries.csv") 

eine Idee zu haben, was ich tat ich auch den Vektor in eine CSV exportiert, die wie folgt aussieht:

"1",2016-01-01 00:00:00 
"2",2016-01-01 00:00:01 
"3",2016-01-01 00:00:02 
"4",2016-01-01 00:00:03 
"5",2016-01-01 00:00:04 
"6",2016-01-01 00:00:05 
"7",2016-01-01 00:00:06 

Leider habe ich keine Ahnung, wie ich mit Schritt 2 und 3 weitermachen soll. Ich habe einige sehr ähnliche Beispiele gefunden (http://www.r-bloggers.com/fix-missing-dates-with-r/, R: Insert rows for missing dates/times), aber als gesamter R noob hatte ich Mühe, diese Beispiele in meine angegebenen Daten zu übertragen .

Einige Hinweise für den Neuling sehr sehr hilfreich wäre - vielen Dank im Voraus :)

+1

Nun, ich würde sagen, dass, anstatt Ihre Meth od, subtrahiere einfach den Zeitstempel mit dem Wert davor. Wenn es größer als 1 ist, geben Sie den Wert aus. Sonst lass es. Wird den Code in einiger Zeit teilen. –

+0

Vielen Dank! Ja, das Subtrahieren der "sollte" Sekunden durch die Datenzeilen, die ich habe, ist die offensichtlichste Lösung (so offensichtlich, dass ich diese Idee nicht hatte, um ehrlich zu sein). Aber ich hatte ohnehin eine weitere Analyse in meinem Kopf, wie zum Beispiel herauszufinden, wo die längsten Datenausfälle auftraten, wie lange sie dort waren und so weiter. Dazu brauche ich sowieso einen Datensatz mit "NA" -Werten. Aber für die ersten Schritte ist Ihre Lösung natürlich so genial wie einfach :) – Bene

+0

Ich habe meinen Code unten als Antwort gegeben, Bene. Überprüfen Sie und lassen Sie mich wissen, wenn es hilft –

Antwort

0

Wenn alles, was Sie die Anzahl der fehlenden Sekunden wollen, kann es einfach viel mehr getan werden. Suchen Sie zuerst die Anzahl der Sekunden in Ihrem Zeitraum und subtrahieren Sie dann die Anzahl der Zeilen in Ihrem Datensatz. Dies könnte in R in dieser Richtung geschehen:

n.seconds <- difftime("2016-06-01 00:00:00", "2016-01-01 00:00:00", units="secs") 
n.rows <- nrow(my.data.frame) 
n.missing.values <- n.seconds - n.rows 

Sie können den Zeitbereich und die Variable des Datenrahmens ändern.

+0

Wenn Sie 'min' und' max' verwenden, um die Zeiten zum Subtrahieren zu berechnen (und vielleicht für vorhandene 'NA's zu berücksichtigen), ist dies eine nette Lösung. – alistaire

1

Im tidyverse,

library(dplyr) 
library(tidyr) 

     # parse datetimes 
df %>% mutate(timestamp = as.POSIXct(timestamp)) %>% 
    # complete sequence to full sequence from min to max by second 
    complete(timestamp = seq.POSIXt(min(timestamp), max(timestamp), by = 'sec')) 

## # A tibble: 7 x 2 
##    timestamp metering 
##    <time> <int> 
## 1 2016-01-01 00:00:00  123 
## 2 2016-01-01 00:00:01  345 
## 3 2016-01-01 00:00:02  243 
## 4 2016-01-01 00:00:03  NA 
## 5 2016-01-01 00:00:04  101 
## 6 2016-01-01 00:00:05  NA 
## 7 2016-01-01 00:00:06  134 

Wenn Sie die Anzahl der NA s (dh die Anzahl der Sekunden ohne Daten) wollen hinzufügen, auf

%>% tally(is.na(metering)) 

## # A tibble: 1 x 1 
##  n 
## <int> 
## 1  2 
+1

Vielen Dank, das sieht aus wie ich suche! Leider bringt es kein Ergebnis - muss ich irgendwo ein paar Zeilen hinzufügen? Ich denke "df" ist der Vektor mit meinen Originaldaten, die ich mit 'df <- read.csv einlesen kann (fpath, header = TRUE, sep =", "), oder? – Bene

+0

Sie können einfach 'df <- read.csv (fpath)'; Die anderen Parameter sind bereits voreingestellt. Um die Ergebnisse zu speichern, ordnen Sie sie etwas zu, z. 'df2 <- df %>% mutate (....' – alistaire

+0

Ja! Es hat funktioniert, vielen Dank! – Bene

1

Sie können überprüfen, welche Werte Ihrer RegularTimeSeries sind in Ihrer gebrochenen Zeitreihe mit which und %in%.Erstellen Sie zunächst BrokenTimeSeries aus Ihrem Beispiel:

RegularTimeSeries <- seq(as.POSIXct("2016-01-01 00:00:00", tz = "UTC"), as.POSIXct("2016-01-01 00:00:30", tz = "UTC"), by = "1 sec") 
BrokenTimeSeries <- RegularTimeSeries[-c(3,6,9)] # remove some seconds 

Dies gibt Ihnen die Indices von Werten innerhalb RegularTimeSeries, die nicht in BrokenTimeSeries:

> which(!(RegularTimeSeries %in% BrokenTimeSeries)) 
[1] 3 6 9 

Dadurch werden die tatsächlichen Werte zurück:

> RegularTimeSeries[which(!(RegularTimeSeries %in% BrokenTimeSeries))] 
[1] "2016-01-01 00:00:02 UTC" "2016-01-01 00:00:05 UTC" "2016-01-01 00:00:08 UTC" 

Vielleicht verstehe ich Ihr Problem falsch, aber Sie können die Anzahl der fehlenden Sekunden einfach abzählen length Ihrer gebrochenen Zeitreihe von RegularTimeSeries oder erhalten Sie die Länge eines der beiden resultierenden Vektoren oben.

> length(RegularTimeSeries) - length(BrokenTimeSeries) 
[1] 3 
> length(which(!(RegularTimeSeries %in% BrokenTimeSeries))) 
[1] 3 
> length(RegularTimeSeries[which(!(RegularTimeSeries %in% BrokenTimeSeries))]) 
[1] 3 

Wenn Sie die Dateien zusammen, um zu sehen, die fehlenden Werte fusionieren möchten, können Sie etwas tun:

#data with regular time series and a "step" 
df <- data.frame(
    RegularTimeSeries 
) 

df$BrokenTimeSeries[RegularTimeSeries %in% BrokenTimeSeries] <- df$RegularTimeSeries 
df$BrokenTimeSeries <- as.POSIXct(df$BrokenTimeSeries, origin="2015-01-01", tz="UTC") 

ergibt:

> df[1:12,] 
    RegularTimeSeries BrokenTimeSeries 
1 2016-01-01 00:00:00 2016-01-01 00:00:00 
2 2016-01-01 00:00:01 2016-01-01 00:00:01 
3 2016-01-01 00:00:02    <NA> 
4 2016-01-01 00:00:03 2016-01-01 00:00:02 
5 2016-01-01 00:00:04 2016-01-01 00:00:03 
6 2016-01-01 00:00:05    <NA> 
7 2016-01-01 00:00:06 2016-01-01 00:00:04 
8 2016-01-01 00:00:07 2016-01-01 00:00:05 
9 2016-01-01 00:00:08    <NA> 
10 2016-01-01 00:00:09 2016-01-01 00:00:06 
11 2016-01-01 00:00:10 2016-01-01 00:00:07 
12 2016-01-01 00:00:11 2016-01-01 00:00:08 
+0

Es ist eine umfassende Post. Plus eins. – akrun

0

Hoffe, es hilft

d <- (c("2016-01-01 00:00:01", 
"2016-01-01 00:00:02", 
"2016-01-01 00:00:03", 
"2016-01-01 00:00:04", 
"2016-01-01 00:00:05", 
"2016-01-01 00:00:06", 
"2016-01-01 00:00:10", 
"2016-01-01 00:00:12", 
"2016-01-01 00:00:14", 
"2016-01-01 00:00:16", 
"2016-01-01 00:00:18", 
"2016-01-01 00:00:20", 
"2016-01-01 00:00:22")) 
d <- as.POSIXct(d) 

for (i in 2:length(d)){ 
    if(difftime(d[i-1],d[i], units = "secs") < -1){ 
    c[i] <- d[i] 
    } 
    } 
class(c) <- c('POSIXt','POSIXct') 
c 
[1] NA      NA      NA      
NA      NA      
[6] NA      "2016-01-01 00:00:10 EST" "2016-01-01 00:00:12  
EST" "2016-01-01 00:00:14 EST" "2016-01-01 00:00:16 EST" 
[11] "2016-01-01 00:00:18 EST" "2016-01-01 00:00:20 EST" "2016-01-01  
00:00:22 EST"