2017-08-26 2 views
2

Je tente de convertir les horodatages dans les données boursières de l'API Google Finance en un format de date/heure plus utilisable.Conversion d'horodatages dans les données boursières Google Finance en date/heure correcte

Je l'ai utilisé data.table::fread pour lire les données here:

fread(<url>) 

     datetime open  high  low close volume 
1: a1497619800 154.230 154.2300 154.2300 154.2300  500 
2:   1 153.720 154.3200 153.7000 154.2500 1085946 
3:   2 153.510 153.8000 153.2000 153.7700 34882 
4:   3 153.239 153.4800 153.1400 153.4800 24343 
5:   4 153.250 153.3000 152.9676 153.2700 20212 

Comme vous pouvez le voir, le format "datetime" est assez étrange. Le format est décrit dans ce link:

Les horodatages complets sont désignés par le «a» principal. Comme ceci: a1092945600. Le numéro après le 'a' est un horodatage Unix. [...]

Les nombres sans «a» en tête sont des «intervalles». Ainsi, par exemple, la deuxième ligne de l'ensemble de données ci-dessous a un intervalle de 1. Vous pouvez multiplier ce nombre par notre taille [...] d'intervalle et l'ajouter au dernier horodatage Unix.

Dans mon cas, la "taille de l'intervalle" est de 300 secondes (5 minutes). Ce format est redémarré au début de chaque nouveau jour et donc essayer de le formater est assez difficile!

Je peux extraire les positions d'index du début de jour en utilisant grep et en cherchant "a";

newDay <- grep(df$V1, pattern = "a") 

Alors mon idée était de diviser la trame de données en morceaux en fonction des positions d'index étendre ensuite les temps unix à chaque jour séparément puis en les peignant de nouveau à un data.table, avant de le ranger.

data.table::split semble que ça va faire le travail, mais je ne sais pas comment lui fournir les pauses du jour pour diviser par des positions d'index, ou s'il y a une manière plus logique d'atteindre le même résultat sans avoir à le décomposer à chaque jour.

Merci.

Répondre

4

Vous suis un y utilisez grepl pour rechercher "a" dans "datetime", ce qui donne un vecteur booléen. cumsum le booléen pour créer une variable de regroupement - pour chaque "a" (TRUE), le compteur va augmenter de un.

Dans chaque groupe, convertissez le premier élément en POSIXct, en utilisant un format et origin (et fuseau horaire, tz? Ajoutez des multiples de la «taille d'intervalle» (300 sec), en utilisant le zéro pour le premier élément et les multiples «datetime» pour les autres.

d[ , time := { 
    t1 <- as.POSIXct(datetime[1], format = "a%s", origin = "1970-01-01") 
    .(t1 + c(0, as.numeric(datetime[-1]) * 300)) 
} 
, by = .(cumsum(grepl("^a", datetime)))] 

d 
#  datetime    time 
# 1: a1497619800 2017-06-16 15:30:00 
# 2:   1 2017-06-16 15:35:00 
# 3:   2 2017-06-16 15:40:00 
# 4:   3 2017-06-16 15:45:00 
# 5:   4 2017-06-16 15:50:00 
# 6: a1500000000 2017-07-14 04:40:00 
# 7:   3 2017-07-14 04:55:00 
# 8:   5 2017-07-14 05:05:00 
# 9:   7 2017-07-14 05:15:00 

Certaines données de jouets:

d <- fread(input = "datetime  
a1497619800 
      1 
      2 
      3 
      4 
a1500000000 
3 
5 
7") 
+1

Bonne solution! J'ai toujours pensé que vous deviez utiliser soit le format ou 'origine'. – Jaap

1

Avec:

DT[grep('^a', date), datetime := as.integer(gsub('\\D+','',date)) 
    ][, datetime := zoo::na.locf(datetime) 
    ][nchar(date) < 4, datetime := datetime + (300 * as.integer(date)) 
     ][, datetime := as.POSIXct(datetime, origin = '1970-01-01', tz = 'America/New_York')][] 

vous obtenez:

   date close  high low  open volume   datetime 
    1: a1500298200 153.57 153.7100 153.57 153.5900 1473 2017-07-17 09:30:00 
    2:   1 153.51 153.8700 153.33 153.7500 205057 2017-07-17 09:35:00 
    3:   2 153.49 153.7800 153.34 153.5800 70023 2017-07-17 09:40:00 
    4:   3 153.68 153.7300 153.42 153.5400 53050 2017-07-17 09:45:00 
    5:   4 153.06 153.7500 153.06 153.7200 120899 2017-07-17 09:50:00 
    ---                  
2348:   937 143.94 144.0052 143.91 143.9917 36651 2017-08-25 15:40:00 
2349:   938 143.90 143.9958 143.90 143.9400 40769 2017-08-25 15:45:00 
2350:   939 143.94 143.9500 143.87 143.8900 56616 2017-08-25 15:50:00 
2351:   940 143.97 143.9700 143.89 143.9400 56381 2017-08-25 15:55:00 
2352:   941 143.74 143.9700 143.74 143.9655 179811 2017-08-25 16:00:00 

données utilisées:

DT <- fread('https://www.google.com/finance/getprices?i=300&p=30d&f=d,t,o,h,l,c,v&df=cpct&q=IBM', skip = 7, header = FALSE) 
setnames(DT, 1:6, c('date','close','high','low','open','volume')) 
+0

Je reçois l'avertissement suivant ce; Message d'avertissement: Dans '[.data.table' (DT [grep ("^a ", date),': = '(datetime, as.integer (gsub (" \\ D + ",: Contraint 'double' RHS à 'integer' pour correspondre au type de la colonne, peut avoir une précision tronquée.Puis permettez à la colonne cible de 'doubler' d'abord (en créant une nouvelle longueur de vecteur 'double' 2352 (nrows de la table entière) 'colonne), ou contraindre RHS à' integer '(par exemple 1L, NA_ [réel | integer] _, as. *, etc) pour rendre votre intention claire et rapide ou bien définir correctement le type de colonne lorsque vous créez – redbaron1981

+0

@ redbaron1981 Je trouve ça aussi, mais rien à craindre, il suffit de dire que ça a changé la classe en entier – Jaap