Skip to content

xyplot.zoo trouble with the index when I use microseconds (type POSIXct)

6 messages · Deepayan Sarkar, Gabor Grothendieck, Laurent Rhelp

#
Dear R-Help-List,

 ?? I have to process time series with a sampling frequency of 1 MHz.
I use the POSIXct format for the date-times with microsecond in a zoo 
object and the xyplot.zoo function to do the graphs.
As I show in the below example I had a trouble to plot the labels on the 
x-axis with an error message. I found a solution but I would like to 
know if I miss something.
The link 
https://stackoverflow.com/questions/7726034/how-r-formats-posixct-with-fractional-seconds 

helped me to understand how to print the POSIXct value to see the 
microseconds thanks to the function myformat.POSIXct:

myformat.POSIXct <- function(x, digits=6)
{
 ? x2 <- round(unclass(x), digits)
 ? attributes(x2) <- attributes(x)
 ? x <- as.POSIXlt(x2,origin="1970-01-01",tz="GMT")
 ? x$sec <- round(x$sec, digits)
 ? format.POSIXlt(x, paste("%Y-%m-%d %H:%M:%OS",digits,sep=""),tz="GMT")

}


## The example giving the error message:

library(lattice)
library(zoo)

##
options(digits = 16) # to see all the digits on the screen
options(digits.secs = 6) # to see the microseconds
# mock data
# a sine with a frequency f0 and two others with a delay
Fs <- 1e+6 # sampling frequency 1 MHz
Ts <- 1/Fs
# frequency of the sinus
f0 <- 100000
t0 <- 1/f0
time <- seq(0, length = 1000, by = Ts)
A1 <- 1
y1 <- A1 * sin(2*pi*f0*time)
y2 <- 2 * A1 * sin(2*pi*f0*(time+0.000002))
y3 <- 3 * A1 * sin(2*pi*f0*(time+0.000005))
## creation of a dataframe:
##
DF <- data.frame( time = time, y1 = y1, y2 = y2, y3 = y3)
# Since I want to allow for the datetime POSIXct format on the x-axis
# for the plot I transform my dataframe in a zoo object
#
# say that my acquisition began at "2021-02-08 09:15:50.000000"
#
mystart <- as.POSIXct("2021-02-08 09:15:50.000000", format = "%Y-%m-%d 
%H:%M:%OS",tz="GMT")
mystart
# To see the correct datetime I use the myformat.POSIXct function
myformat.POSIXct(mystart)
##
## using the method seq.POSIXct as following doesn't work:
## mydatetime <- seq( mystart , length = nrow(DF), by = "0.000001 sec")
## head( myformat.POSIXct(mydatetime) )
## if I use the following command it works:
mydatetime <- seq( mystart , length = nrow(DF), by = 0.000001)
head( myformat.POSIXct(mydatetime) )
## I do the zoo object:
DF.z <- zoo(DF[,-1],order.by = mydatetime)
## We don't see the correct value for the index:
head(DF.z)
# time??????????????????? y1 y2???????????????????? y3
# 2021-02-08 09:15:50.000000 0e+00 0.000000000000000e+00 
1.902113032590307e+00? 3.673819061467132e-16
# 2021-02-08 09:15:50.000000 1e-06 5.877852522924730e-01 
1.902113032590307e+00 -1.763355756877419e+00
# 2021-02-08 09:15:50.000001 2e-06 9.510565162951535e-01 
1.175570504584947e+00 -2.853169548885460e+00
# 2021-02-08 09:15:50.000003 3e-06 9.510565162951536e-01 
1.133099690464601e-15 -2.853169548885460e+00
# 2021-02-08 09:15:50.000004 4e-06 5.877852522924736e-01 
-1.175570504584946e+00 -1.763355756877420e+00
# 2021-02-08 09:15:50.000005 5e-06 5.665498452323003e-16 
-1.902113032590306e+00 -3.399299071393802e-15
# If I use myformat.POSIXct I see that the index is correct in the 
object DF:
head(myformat.POSIXct(index(DF.z)))
## and when I plot I have an error:
xyplot(?? DF.z
 ????????? , screens = c(1,1,1)
 ????????? , type = "l"
 ????????? , col = c("red","blue","black")

)

# Error in prettyDate_TMP(x, ...) : range too small for min.n

# if I process by hand the plot of the labels on the x-axis it works:
#
myend <- tail(mydatetime,1)

myticks <- seq( mystart , to = myend , length = 5)
mylabels <- format(myticks,"%H:%M:%OS")

xyplot(????? DF.z
 ???????????? , screens = c(1,1,1)
 ???????????? , type = "l"
 ???????????? , col = c("red","blue","black")
 ???????????? , scales = list(
 ???????????????? y= list(relation = "free", abbreviate=TRUE),
 ???????????????? x = list( at = myticks, labels = mylabels
 ?????????????????????? , rot = 45, cex = 0.5)
 ?????????? )
)
# The microseconds are well taken into account with the window function
# if I want to plot only 100 microseconds but there is of course the same
# trouble for the plot

myend <- as.POSIXct("2021-02-08 09:15:50.000100", format = "%Y-%m-%d 
%H:%M:%OS",tz="GMT")
myformat.POSIXct(myend)

DF.w <- window( DF.z ,start = mystart, end = myend)

myticks <- seq( mystart , to = myend , length = 5)
mylabels <- format(myticks,"%H:%M:%OS")

xyplot(????? DF.w
 ???????????? , screens = c(1,1,1)
 ???????????? , type = "l"
 ???????????? , col = c("red","blue","black")
)

## Error in prettyDate_TMP(x, ...) : range too small for min.n

xyplot(????? DF.w
 ???????????? , screens = c(1,1,1)
 ???????????? , type = "l"
 ???????????? , col = c("red","blue","black")
 ???????????? , scales = list(
 ?????????????? y= list(relation = "free", abbreviate=TRUE),
 ?????????????? x = list( at = myticks, labels = mylabels
 ???????????????????????? , rot = 45, cex = 0.5)
 ???????????? )
)

May you please tell me if I miss something in the way to use POSIXct
with microseconds in a zoo object ?

Thank you
Laurent
#
I assume that this is a lattice problem.  Replacing xyplot with plot
and using all the same arguments there is no error.
On Mon, Feb 22, 2021 at 11:26 AM Laurent Rhelp <LaurentRHelp at free.fr> wrote:
--
Statistics & Software Consulting
GKX Group, GKX Associates Inc.
tel: 1-877-GKX-GROUP
email: ggrothendieck at gmail.com
#
On Mon, Feb 22, 2021 at 9:56 PM Laurent Rhelp <LaurentRHelp at free.fr> wrote:
At least the immediate problem is that

lattice:::prettyDate_TMP(range(mydatetime))
# Error in lattice:::prettyDate_TMP(range(mydatetime)) :
# range too small for min.n

grDevices:::prettyDate(range(mydatetime))
# [1] "2021-02-08 09:15:48 GMT" "2021-02-08 09:15:49 GMT"
# [3] "2021-02-08 09:15:50 GMT" "2021-02-08 09:15:51 GMT"
# [5] "2021-02-08 09:15:52 GMT" "2021-02-08 09:15:53 GMT"

So the version in lattice (which was supposed to be a temporary
stopgap till R 2.12 was released) has not kept up. I will fix.

Does the output above look OK to you?

Best,
-Deepayan
#
Le 22/02/2021 ? 18:01, Deepayan Sarkar a ?crit?:
It is ok for me except the fact that I would like to see on the x-axis 
labels the fractional seconds, at least the milliseconds.

  
    
#
Also, it might be better to simply use seconds as the time. In that
case both plot and xyplot run without error.

 time(DF.w) <- as.POSIXlt(time(DF.w))$sec
 # now run plot or xyplot as before

On Mon, Feb 22, 2021 at 11:56 AM Gabor Grothendieck
<ggrothendieck at gmail.com> wrote:

  
    
#
yes, good idea, eventually here's what I will do:

time(DF.w) <- as.POSIXlt(time(DF.w))$sec
myticks <- round(pretty(time(DF.w)),6)
mylabels <- as.character(formatC(myticks,format = 
"f",digits=6,width=9,flag=" "))

xyplot(????? DF.w
 ?, xlab = paste0("Seconds from ",format(mystart,"%Y-%m-%d %H:%M"))
 ?, type = "l"
 ?, screens = 1
 ?,? col = c("red","blue","black")
 ?,? scales = list( y= list(relation = "free", abbreviate=TRUE)
 ????????????????????? , x = list( at = myticks, labels = mylabels
 ????????????????????? , rot = 45, abbreviate = FALSE
 ????????????????????? , cex = 0.6)
 ???????????? )
)

Thank you



Le 22/02/2021 ? 19:32, Gabor Grothendieck a ?crit?: