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
220 stars 71 forks source link

rowMeans / rowSums on xts objects #281

Closed harvey131 closed 1 year ago

harvey131 commented 5 years ago

Description

Are you willing to accept a pull request for functions to compute the rowMeans / rowSums on xts objects and return the object as an xts object?

Minimal, reproducible example

  library(xts) 
  x <- .xts(matrix(rnorm(30), ncol=3), 1:10, dimnames=list(NULL, c('a','b','c')) )
  rowSums.xts <- function(x, na.rm=F, name='sum')
  {
    r <- matrix(rowSums(x, na.rm=na.rm), dimnames = list(NULL, name))
    xcoredata(r) <- xcoredata(x)
    return(r)
  }
  y <- rowSums.xts(x)
  all.equal(as.numeric(y), rowSums(x))

> head(x)
                              a           b          c
1969-12-31 19:00:01  0.01232592  0.95329017  1.9034343
1969-12-31 19:00:02 -1.16103541  0.97207964  0.4450646
1969-12-31 19:00:03 -0.34155275 -1.02157653  0.9267735
1969-12-31 19:00:04  2.00349972  0.09655199  0.1963148
1969-12-31 19:00:05 -0.15090314  0.58546213  0.5210464
1969-12-31 19:00:06  1.31294536 -0.28664174 -0.5481664

> head(y)
                           sum
1969-12-31 19:00:01  2.8690504
1969-12-31 19:00:02  0.2561089
1969-12-31 19:00:03 -0.4363558
1969-12-31 19:00:04  2.2963665
1969-12-31 19:00:05  0.9556054
1969-12-31 19:00:06  0.4781372
ethanbsmith commented 1 year ago

i dont think this is dispatching properly

Restarting R session...

> rowMeans(data.frame(a=1:3,b=4:6))
[1] 2.5 3.5 4.5
> library(xts)
Loading required package: zoo

Attaching package: ‘zoo’

The following objects are masked from ‘package:base’:

    as.Date, as.Date.numeric

Attaching package: ‘xts’

The following objects are masked from ‘package:base’:

    rowMeans, rowSums

> rowMeans(data.frame(a=1:3,b=4:6))
Error in UseMethod("rowMeans") : 
  no applicable method for 'rowMeans' applied to an object of class "data.frame"
> sessionInfo()
R version 4.2.1 (2022-06-23 ucrt)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 19044)

Matrix products: default

locale:
[1] LC_COLLATE=English_United States.utf8  LC_CTYPE=English_United States.utf8    LC_MONETARY=English_United States.utf8 LC_NUMERIC=C                           LC_TIME=English_United States.utf8    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] xts_0.12.2.1 zoo_1.8-11  

loaded via a namespace (and not attached):
[1] compiler_4.2.1    cli_3.4.1         tools_4.2.1       grid_4.2.1        lattice_0.20-45   sessioninfo_1.2.2
joshuaulrich commented 1 year ago

I forgot to register the default S3 method. Ugh. F- for not adding unit tests.

Thankfully this isn't on CRAN. Whew.

joshuaulrich commented 1 year ago

This should be fixed now. Thanks for the report Ethan!

joshuaulrich commented 1 year ago

...these still need to be documented.

Also, I don't feel great about masking the base functions. And I've wanted something more general: getting reasonable output from calling apply() on an xts object, for example. I'm thinking something like rowapply() and colapply() functions. I'll open another issue to discuss.

ethanbsmith commented 1 year ago

a bit late jumping in here. I currently have similar functions that use the matrixstats package for the underlying implementation for a number of rowXXX type functions. this solution creates some overlap, so wondering if there is a way to allow use of all the matrixstats rowXXX functions?

zeileis commented 1 year ago

When we introduce rowapply() and colapply(), one idea could be to dispatch certain values of deparse(substitute(FUN)) provided that requireNamespace("matrixstats"). Not sure how much overhead this will create, though, and whether there would be other implementations one might want to special case.

joshuaulrich commented 1 year ago

My intention is to remove xts::rowMeans() and xts::rowSums() when the rowapply() function is added. I don't like that they mask the base functions, and I prefer the more general solution.

I agree with Achim about dispatching to specialized functions for certain operations, if they're available. For example, rowapply(x, mean) could call base::rowMeans() (or matrixStats::rowMeans2()).