2017-08-05 4 views
1

Je ne suis pas bon en "R" et je ne suis pas sûr de la façon de réorganiser et de sous-traiter les données de séries chronologiques. Désolé, si cette question semble stupide. J'ai une série chronologique de données sur la marée avec quatre valeurs par jour (avec des valeurs manquantes aussi). Deux valeurs pour la marée haute et deux pour la marée basse. L'heure et la date sont indiquées dans la même colonne mais dans des lignes différentes. Maintenant, je veux sous-ensemble les données seulement pour la journée (de 7h00 à 19h00) pas pour la nuit. Ensuite, je veux que les données soient disposées en trois colonnes seulement: i) Date, ii) Heure et iii) Marée. Pour Tide, j'ai seulement besoin de valeurs minimum et maximum. Voici un exemple des données et l'arrangement souhaité des données. Pour chaque date, les données sont organisées en trois lignes similaires à l'exemple.Réarrangement des données de séries temporelles

1/1/2011 Low High Low NA 
Time 2:58 AM 9:38 AM 5:19 PM NA 
Tide 1.2 m 2.2 m 0.6 m NA 
1/2/2011 High Low High Low 
Time 2:07 AM 4:22 AM 10:19 AM 6:07 PM 
Tide 1.4 m 1.3 m 2.3 m 0.4 m 

Date Time Tide 
1/1/2011 17:19 0.6 
1/1/2011 9:38 2.2 
1/2/2011 2:07 1.4 
1/2/2011 18:07 0.4 
+0

Par curiosité, où êtes-vous vos données à partir? Cette connaissance peut aider à garantir la robustesse de toute solution, c'est-à-dire fonctionner avec les futures collectes de données. – Woodstock

+0

@Woodstock, ces données proviennent d'Abu Dahbi. Les données sont de 12 ans, donc beaucoup de données à traiter. – Gull

Répondre

1

L'entrée, DF est supposée être comme dans la remarque ci-dessous. Le vecteur de groupement a un élément par rangée de DF et est égal à c(1, 1, 1, 2, 2, 2, ...). Les autres moyens de calculer g seraient n <- nrow(DF); g <- gl(n, 3, n) ou n <- nrow(DF); g <- rep(1:3, n, n).

Nous utilisons ensuite by pour diviser DF en groupes et appliquer la fonction anonyme indiquée à chaque groupe comme défini par g.

La fonction anonyme combine la date et le temps du groupe en cours pour créer la date/temps dt faisant usage du fait que la date commune est x[1,1] et les temps avant d'être nettoyé sont en x[2,-1]. En utilisant dt et les marées au x[2, -1] (avant d'être nettoyé), il calcule chacune des trois colonnes en les rangeant dans une trame de données. Ensuite, il y a une ligne commentée qui supprime les valeurs NA. Si vous voulez ce décommenter. Sous-ensemble de la trame de données obtenue jusqu'à présent à la période de 7h à 19h et prendre en outre les deux lignes constituées de la marée min et max. Nous trions cela par le temps.

Enfin, do.call("rbind", ...) regroupe les groupes dans une trame de données globale.

Aucun emballage n'est utilisé.

g <- cumsum(grepl("\\d", DF$V1)) 
Long <- do.call("rbind", by(DF, g, function(x) { 
    dt <- as.POSIXct(paste(x[1,1], as.matrix(x[2, -1])), format = "%m/%d/%Y %I:%M %p") 
    X <- data.frame(Date = as.Date(dt), 
        Time = format(dt, "%H:%M"), 
        Tide = as.numeric(sub("m", "", as.matrix(x[3, -1]))), 
        stringsAsFactors = FALSE) 
    # X <- na.omit(X) 
    X <- subset(X, Time >= "07:00" & Time <= "19:00") 
    X <- X[c(which.min(X$Tide), which.max(X$Tide)), ] 
    X[order(X$Time), ] 
})) 

donnant les éléments suivants - noter que la troisième ligne de la sortie de la question n'est pas 7 heures-19 heures si la sortie diffère nécessairement ici.

> Long 
      Date Time Tide 
1.2 2011-01-01 09:38 2.2 
1.3 2011-01-01 17:19 0.6 
2.3 2011-01-02 10:19 2.3 
2.4 2011-01-02 18:07 0.4 

Note: L'entrée DF est supposée comme suit sous forme reproductible:

Lines <- "1/1/2011,Low,High,Low,NA 
Time,2:58 AM,9:38 AM,5:19 PM,NA 
Tide,1.2 m,2.2 m,0.6 m,NA 
1/2/2011,High,Low,High,Low 
Time,2:07 AM,4:22 AM,10:19 AM,6:07 PM 
Tide,1.4 m,1.3 m,2.3 m,0.4 m" 
DF <- read.table(text = Lines, sep = ",", as.is = TRUE) 
+0

J'essaie de suivre ce que vous avez fait. Couper et coller votre code, ma sortie a la deuxième rangée comme '1.3 2011-01-02 17:19 0.6' -> note c'est le 2 janvier, pas le 1er janvier ... ai-je gâcher quelque part? – Woodstock

+0

Démarrer une nouvelle session de R, copier et coller le code dans la note pour générer l'entrée, puis copiez et collez le code dans la réponse elle-même pour obtenir le résultat. Cela devrait correspondre au résultat affiché dans la réponse. –

0

Si la liste est pas trop long, cet effort serait plus simple de le faire dans une feuille de calcul simplement par les cellules de cartographie et de filtrage . Mais une façon de le faire en R avec zoo et tidyverse est le suivant:

En supposant que les dataframes d'origine ont leurs colonnes nommé C1: C5

 C1  C2  C3  C4  C5 
    <chr> <chr> <chr> <chr> <chr> 
1 1/1/2010  Low High  Low <NA> 
2  Time 2:58 AM 9:38 AM 5:19 PM <NA> 
3  Tide  1.2  2.2  0.6 <NA> 
4 1/2/2011 High  Low  High  Low 
5  Time 2:07 AM 4:22 AM 10:19 AM 6:07 PM 
6  Tide  1.4  1.3  2.3  0.4 

DF <- DF %>% 
     mutate(Date = as.Date(gsub("Tide|Time","", C1), format = "%d/%m/%Y")) 
DF <- DF %>% 
     mutate(Date = na.locf(DF$Date, na.rm = TRUE), 
         C1 = gsub("[[:digit:]]|\\/", "", C1), 
         Type = if_else(nchar(C1) == 0, "TideType", C1)) %>% 
       select(Date, Type, C2:C5) %>% 
       gather(oColumn, Value, -c(Date, Type)) %>% 
       spread(key = Type, value = Value) %>% 
       select(Date, Time, Tide) %>% 
       filter(complete.cases(.)) 
DF <- DF %>% 
     mutate(Time = ymd_hm(paste(DF$Date, DF$Time, sep = " ")), 
       Tide = as.numeric(Tide)) 
DF <- DF %>% 
     mutate(DayNight = (DF$Time) %within% 
      interval(as.POSIXlt(DF$Date) + (7*60*60), as.POSIXlt(DF$Date) + (19*60*60))) %>% 
     filter(DayNight == TRUE) %>% 
     select(-DayNight)) %>% 
     group_by(Date) %>% 
     filter(Tide == max(Tide) | min(Tide)) 

DF 
Source: local data frame [4 x 3] 
Groups: Date [2] 

     Date    Time Tide 
     <date>    <dttm> <dbl> 
1 2010-01-01 2010-01-01 09:38:00 2.2 
2 2010-01-01 2010-01-01 17:19:00 0.6 
3 2011-02-01 2011-02-01 10:19:00 2.3 
4 2011-02-01 2011-02-01 18:07:00 0.4 

Notez que « Date » est un type de date de Object et "Time" est un type Posixct d'objet date-heure. Vous pourriez vouloir convertir "Time" en un vecteur de minutes.