joshuaulrich / xts

Extensible time series class that provides uniform handling of many R time series classes by extending zoo.
http://joshuaulrich.github.io/xts/
GNU General Public License v2.0
219 stars 70 forks source link

Make str() output more accurate and descriptive #378

Closed joshuaulrich closed 1 year ago

joshuaulrich commented 1 year ago

Several things in str() have slightly annoyed me over the years... I finally got annoyed enough to do something about it.

library(xts)
options(digits.secs = 6)
x <- .xts(1:10, 1:10 + runif(10), tzone = "UTC", attr1 = "hello", attr2 = "world")

str(x)
## An 'xts' object on 1970-01-01 00:00:01.382967/1970-01-01 00:00:10.929376 containing:
##   Data: int [1:10, 1] 1 2 3 4 5 6 7 8 9 10
##   Indexed by objects of class: [POSIXct,POSIXt] TZ: UTC
##   xts Attributes:  
## List of 2
##  $ attr1: chr "hello"
##  $ attr2: chr "world"

# technically true, but it's not zero-length
str(xts::.xts(, 1))
## An 'xts' object of zero-width

# technically true, but it's also zero-length... so it's empty
str(.xts(, numeric(0)))
## An 'xts' object of zero-width

# this is not true; it has a width but no observations
str(xts::.xts(cbind(a = 1, b = 2), 1)["1900"])
## An 'xts' object of zero-width
  1. The time range at the top can be hard to read, especially for POSIXct with sub-seconds.
  2. Printing a few data values doesn't tell you much, and [1:10, 1] could be [10, 1].
  3. xts objects don't have row names, so we don't need to print "dimnames", just the column names.
  4. Only the first 'n' column names are printed. I would like to be able to control that.
  5. The xts attributes aren't indented.

Here's the result of my first draft:

str(x)
## An xts object on 1970-01-01 00:00:01.662144 / 1970-01-01 00:00:10.769142 containing:
##   Data:    integer [10, 1]
##   Index:   class [POSIXct,POSIXt], TZ [UTC]
##   xts Attributes:
##     $ attr1: chr "hello"
##     $ attr2: chr "world"

str(.xts(, 1))
## A zero-width xts object on 1969-12-31 18:00:01 / 1969-12-31 18:00:01 containing:
##   Data:    double [0, 0]
##   Index:   class [POSIXct,POSIXt], TZ []

str(.xts(cbind(a = 1, b = 2), 1)["1900"])
## A zero-length xts object
##   Data:    double [0, 2]
##   Columns: a, b
##   Index:   class [POSIXct,POSIXt], TZ []

str(.xts(, numeric(0)))
## An empty xts object
##   Data:    double [0, 0]
##   Index:   class [POSIXct,POSIXt], TZ []
ethanbsmith commented 1 year ago

like it, much cleaner. just a few thoughts

  1. since the dims are part of the "Data" output line, is there value in the "zero width"/"zero length" text?
  2. periodicity would be nice. eg: ## an xts object with Weekly periodicity from 2016-06-24 to 2022-10-21 containing:
joshuaulrich commented 1 year ago

Thanks for the quick feedback!

  1. My thought was that it makes those descriptions of xts objects clearer and more commonly used. Some functions behave differently for zero-width, zero-length, and/or empty xts objects.
  2. I like that!

I just thought of something else: add the number of index observations to the output, (e.g. Index: (POSIXct, POSIXt) [100] TZ: UTC). That's helpful for the zero-width case when there is a non-zero-length index.

joshuaulrich commented 1 year ago

This is going into the 0.13.0 release.