'R+Tidyverse: Tibbles don't appear to store milliseconds

I have a CSV with many values. Among them are times stored like this:

1:34.434

Using readr, I form them into a tibble, and use dplyr to cut out all the unnecessary rows and columns.

lapData <- read_csv("sampledata/sampledata.csv")
lapData <- dplyr::select(lapData, 
                         Driver, Lap, Penalty, 'Lap Time', 'Lap type', 
                         'Pressure FR', 'Pressure FL', 'Pressure RR', 'Pressure RL', 
                         'Temp FR', 'Temp FL', 'Temp RR', 'Temp RL',
                         'Road Temp')
lapData <- dplyr::filter(lapData, Driver == "[personal info]")
lapData <- dplyr::filter(lapData, is.na(Penalty))
lapData <- dplyr::filter(lapData, Lap > 1)

I then use print(ggplot(data = lapData, mapping = aes(Lap, 'Lap Time')) + geom_line()) to print the data, and it looks like this:
plot showing loss of precision
If it isn't clear, the vertices of the graph line are rounded to the seconds value instead of using the full milisecond precision, which I would like to have.
If I then print(lapData), I see the following entries under 'Lap Time':
printed tibble
I did some research, and found this, which seems to indicate that the loss of precision in the printout from the tibble is inconsequential, and the full data is still stored in the tibble. However, the plot contradicts this statement.

How do I get the plot to show the full millisecond resolution?



Solution 1:[1]

To avoid readr's guessing, you could use conventional read.csv.

r <- read.csv('foo.csv')

Next, it is probably better to use pure milliseconds. For this, we may use strptime with"%M:%OS" which returns the beautiful "POSIXlt" format that we can put in a with and play with the minutes and seconds.

r$lap_time_ms <- with(strptime(r$lap_time, format="%M:%OS"), 6e4*min + 1e3*sec)

r
#   lap_time lap          x lap_time_ms
# 1 1:29.134   1  0.9292880       89134
# 2 1:26.233   2 -0.3301566       86233
# 3 1:28.033   3 -1.5426225       88033
# 4 1:26.434   4 -0.9961375       86434
# 5 1:26.634   5  1.1610645       86634
# 6 1:27.634   6 -0.2817558       87634

If you want a y-axis formatted in <secs>:<mins> format, use a sequence along the range of the lap times with steps in seconds.

at <- do.call(seq, c(as.list(range(ceiling(r$lap_time_ms/1e3))*1e3), 1e3))
sq <- at %/% 1e3 |> {\(.) paste(. %/% 60, . %% 60, sep=':')}()

plot(lap_time_ms ~ lap, r, type='l', yaxt='n')
axis(2, at=at, labels=sq)

enter image description here

This should also be possible with ggplot2 package.


Data:

dat <- read.table(header=TRUE, text='lap_time
1:29.134
1:26.233
1:28.033
1:26.434 
1:26.634
1:27.634
') |> transform(lap=1:6, x=rnorm(6))
write.csv(dat, 'foo.csv', row.names=FALSE)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1