Création d'un objet XTS résultats dans horodatages modifiés
-
27-10-2019 - |
Question
Supposons que j'ai:
R> str(data)
'data.frame': 4 obs. of 2 variables:
$ datetime: Factor w/ 4 levels "2011-01-05 09:30:00.001",..: 1 2 3 4
$ price : num 18.3 18.3 18.3 18.3
R> data
datetime price
1 2011-01-05 09:30:00.001 18.31
2 2011-01-05 09:30:00.321 18.33
3 2011-01-05 09:30:01.511 18.33
4 2011-01-05 09:30:02.192 18.34
Lorsque je tente de charger ce dans un objet xts
les horodatages sont subtilement modifiés:
R> x <- xts(data[-1], as.POSIXct(strptime(data$datetime, '%Y-%m-%d %H:%M:%OS')))
R> str(x)
An ‘xts’ object from 2011-01-05 09:30:00.000 to 2011-01-05 09:30:02.191 containing:
Data: num [1:4, 1] 18.3 18.3 18.3 18.3
- attr(*, "dimnames")=List of 2
..$ : NULL
..$ : chr "price"
Indexed by objects of class: [POSIXct,POSIXt] TZ:
xts Attributes:
NULL
R> x
price
2011-01-05 09:30:00.000 18.31
2011-01-05 09:30:00.321 18.33
2011-01-05 09:30:01.510 18.33
2011-01-05 09:30:02.191 18.34
Vous remarquerez que les horodateurs ont été modifiés. La première entrée se produit maintenant à 09:30:00.000
au lieu de ce que les données d'origine dit, 09:30:00.001
. Les troisième et quatrième lignes sont également incorrectes.
Qu'est-ce qui cause? Est-ce que je fais quelque chose de fondamentalement mauvais? J'ai essayé différentes incantations pour obtenir les données dans un objet xts
et ils semblent tous avoir ce comportement.
EDIT: Ajouter sessionInfo()
R> sessionInfo()
R version 2.13.1 (2011-07-08)
Platform: x86_64-unknown-linux-gnu (64-bit)
locale:
[1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C LC_TIME=en_US.UTF-8
[4] LC_COLLATE=C LC_MONETARY=C LC_MESSAGES=en_US.UTF-8
[7] LC_PAPER=en_US.UTF-8 LC_NAME=C LC_ADDRESS=C
[10] LC_TELEPHONE=C LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] xts_0.8-2 zoo_1.7-4
loaded via a namespace (and not attached):
[1] grid_2.13.1 lattice_0.19-30 tools_2.13.1
EDIT 2: Si je modifie mes données source à la précision microseconde comme suit:
datetime,price
2011-01-05 09:30:00.001000,18.31
2011-01-05 09:30:00.321000,18.33
2011-01-05 09:30:01.511000,18.33
2011-01-05 09:30:02.192000,18.34
Et puis chargez donc j'ai:
R> test
datetime price
1 2011-01-05 09:30:00.001000 18.31
2 2011-01-05 09:30:00.321000 18.33
3 2011-01-05 09:30:01.511000 18.33
4 2011-01-05 09:30:02.192000 18.34
Et puis, enfin, le convertir en un objet xts
et définir le format d'index:
R> x <- xts(test[,-1], as.POSIXct(strptime(test$datetime, '%Y-%m-%d %H:%M:%OS')))
R> indexFormat(x) <- '%Y-%m-%d %H:%M:%OS6'
R> x
[,1]
2011-01-05 09:30:00.000999 18.31
2011-01-05 09:30:00.321000 18.33
2011-01-05 09:30:01.510999 18.33
2011-01-05 09:30:02.191999 18.34
Vous pouvez voir l'effet aussi bien. J'espérais que l'ajout de la précision supplémentaire aiderait, mais malheureusement, il ne fonctionne pas.
EDIT 3: S'il vous plaît voir @ réponse de dwin pour un cas de test de bout en bout qui reproduit ce comportement.
EDIT 4: Le comportement ne semble pas être orientée milliseconde. L'exemple suivant montre le même résultat modifié d'un horodatage de résolution de microseconde. Si je change mes données d'entrée:
R> data
datetime price
1 2011-01-05 09:30:00.001001 18.31
2 2011-01-05 09:30:00.321001 18.33
3 2011-01-05 09:30:01.511001 18.33
4 2011-01-05 09:30:02.192005 18.34
Et puis créez un objet xts
:
R> x <- xts(data[-1],
as.POSIXct(strptime(as.character(data$datetime), '%Y-%m-%d %H:%M:%OS')))
R> indexFormat(x) <- '%Y-%m-%d %H:%M:%OS6'
R> x
price
2011-01-05 09:30:00.001000 18.31
2011-01-05 09:30:00.321001 18.33
2011-01-05 09:30:01.511001 18.33
2011-01-05 09:30:02.192004 18.34
EDIT 5: Il semble être une question de précision à virgule flottante. Observer:
R> t <- as.POSIXct("2011-01-05 09:30:00.001001")
R> t
[1] "2011-01-05 09:30:00.001 CST"
R> as.numeric(t)
[1] 1294241400.0010008812
Cette exposition le comportement d'erreur, et est compatible avec l'exemple EDIT 4. Cependant, en utilisant un exemple qui ne montre pas l'erreur:
R> t <- as.POSIXct("2011-01-05 09:30:01.511001")
R> t
[1] "2011-01-05 09:30:01.511001 CST"
R> as.numeric(t)
[1] 1294241401.5110011101
Il semble que xts
ou d'un composant sous-jacent est arrondi vers le bas plutôt que le plus proche?
La solution
Il semble que le problème est que dans l'impression. L'utilisation data
originale de l'OP:
ind <- as.POSIXct(strptime(data$datetime, '%Y-%m-%d %H:%M:%OS'))
as.numeric(ind)*1e6 # as expected
# [1] 1294241400001000 1294241400321000 1294241401511000 1294241402192000
ind # wrong
# [1] "2011-01-05 09:30:00.000 CST" "2011-01-05 09:30:00.321 CST"
# [3] "2011-01-05 09:30:01.510 CST" "2011-01-05 09:30:02.191 CST"
x <- xts(data[-1], ind)
x # wrong
# price
# 2011-01-05 09:30:00.000 18.31
# 2011-01-05 09:30:00.321 18.33
# 2011-01-05 09:30:01.510 18.33
# 2011-01-05 09:30:02.191 18.34
as.numeric(index(x))*1e6 # but the underlying index values are as expected
# [1] 1294241400001000 1294241400321000 1294241401511000 1294241402192000
Autres conseils
Vous avez votre temps dans un facteur:
R> str(data)
'data.frame': 4 obs. of 2 variables:
$ datetime: Factor w/ 4 levels "2011-01-05 09:30:00.001",..: 1 2 3 4
[...]
Ce n'est pas le meilleur endroit pour commencer. Vous devez convertir en caractère. Par conséquent au lieu de
x <- xts(data[-1], as.POSIXct(strptime(data$datetime, '%Y-%m-%d %H:%M:%OS')))
Je suggère
x <- xts(data[-1],
order.by=as.POSIXct(strptime(as.character(data$datetime),
'%Y-%m-%d %H:%M:%OS')))
Dans mon expérience, le as.character()
autour d'un facteur est essentiel. Les facteurs sont puissants pour la modélisation, ils sont cependant un peu gênant quand vous les renversez de lecture de données. Utilisez stringsAsFactor=FALSE
à votre avantage et de les éviter à l'importation de données.
Modifier Donc, cela semble pointer vers la mise en oeuvre strptime / strftime. Pour rendre les choses plus intéressantes, R prend certains d'entre eux à partir du système d'exploitation et réimplémente certains dans src/main/datetime.c
.
De plus, attention à la plus petite epsilon vous pouvez ajouter à une variable de temps et ont encore R les voir comme égaux. Sur mon système Linux 64 bits, cela se produit 10 ^ -7:
R> sapply(seq(1, 8), FUN=function(x) identical(now, now+1/10^x))
[1] FALSE FALSE FALSE FALSE FALSE FALSE TRUE TRUE
R>
Je poste ce juste pour que les gens qui veulent explorer peut avoir un exemple reproductible qui montre qu'il se passe sur plus qu'un simple système de l'OP. as.character
au facteur ne tient pas de se produire.
dat <- read.table(textConnection(" datetime\tprice
1\t2011-01-05 09:30:00.001\t18.31
2\t2011-01-05 09:30:00.321\t18.33
3\t2011-01-05 09:30:01.511\t18.33
4\t2011-01-05 09:30:02.192\t18.34"), header =TRUE, sep="\t")
as.character(dat$datetime)
#[1] "2011-01-05 09:30:00.001" "2011-01-05 09:30:00.321" "2011-01-05 09:30:01.511"
#[4] "2011-01-05 09:30:02.192"
strptime(as.character(dat$datetime), '%Y-%m-%d %H:%M:%OS')
#[1] "2011-01-05 09:30:00" "2011-01-05 09:30:00" "2011-01-05 09:30:01"
#[4] "2011-01-05 09:30:02"
as.POSIXct(strptime(as.character(dat$datetime),
'%Y-%m-%d %H:%M:%OS'))
#[1] "2011-01-05 09:30:00 EST" "2011-01-05 09:30:00 EST" "2011-01-05 09:30:01 EST"
#[4] "2011-01-05 09:30:02 EST"
x <- xts(dat[-1],
order.by=as.POSIXct(strptime(as.character(dat$datetime),
'%Y-%m-%d %H:%M:%OS')))
x
#### price
2011-01-05 09:30:00 18.31
2011-01-05 09:30:00 18.33
2011-01-05 09:30:01 18.33
2011-01-05 09:30:02 18.34
indexFormat(x) <- '%Y-%m-%d %H:%M:%OS6'
x
price
2011-01-05 09:30:00.000999 18.31
2011-01-05 09:30:00.321000 18.33
2011-01-05 09:30:01.510999 18.33
2011-01-05 09:30:02.191999 18.34
sessionInfo()
R version 2.13.1 RC (2011-07-03 r56263)
Platform: x86_64-apple-darwin9.8.0/x86_64 (64-bit)
locale:
[1] en_US.UTF-8/en_US.UTF-8/C/C/en_US.UTF-8/en_US.UTF-8
attached base packages:
[1] grid splines stats graphics grDevices utils datasets methods
[9] base
other attached packages:
[1] xts_0.8-2 zoo_1.7-4 sculpt3d_0.2-2 RGtk2_2.20.12
[5] rgl_0.92.798 survey_3.24 hexbin_1.26.0 spam_0.23-0
[9] xtable_1.5-6 polspline_1.1.5 Ryacas_0.2-10 XML_3.4-0
[13] rms_3.3-1 Hmisc_3.8-3 survival_2.36-9 sos_1.3-0
[17] brew_1.0-6 lattice_0.19-30
loaded via a namespace (and not attached):
[1] cluster_1.14.0 tools_2.13.1