Denis
Denis

Reputation: 12087

How do you add a column to a univariate zoo series?

Suppose I have a univariate zoo series:

v <- read.zoo(data.frame(dt=c(as.Date('2019-01-01')+1:10), vals=1:10))
v
2019-01-02 2019-01-03 2019-01-04 2019-01-05 2019-01-06 2019-01-07 2019-01-08 2019-01-09 2019-01-10 2019-01-11 
         1          2          3          4          5          6          7          8          9         10 

I would like to turn this into a regular zoo series with an additional column val2 which has let's say "test":

           val  val2
2019-01-02  1     test
2019-01-03  2     test
...

I tried the following. It logically shouldn't work (since the zoo object is univariate) but I figured since this works for a data.frame it might work or I'd get an error or warning to guide me towards the right path which surprisingly didn't happen but it did something REALLY BAD...:

   cbind(v, val2="test")
               v    val2
    1970-01-02 <NA> test
    2019-01-02 1    <NA>
    2019-01-03 2    <NA>
    2019-01-04 3    <NA>
    2019-01-05 4    <NA>
    2019-01-06 5    <NA>
    2019-01-07 6    <NA>
    2019-01-08 7    <NA>
    2019-01-09 8    <NA>
    2019-01-10 9    <NA>
    2019-01-11 10   <NA>

I would have expected it to fill val2 with the value: "test" or give me some warnings/errors.

Upvotes: 0

Views: 454

Answers (2)

G. Grothendieck
G. Grothendieck

Reputation: 270428

A zoo object's data is a matrix and a matrix cannot have mixed types. In partcular, it cannot have a mix of numeric and character data.

Suppose instead that the new column is val2 shown below. Then

library(zoo)

val2 <- 101:110
cbind(val = v, val2) # v is from question

giving:

           val val2
2019-01-02   1  101
2019-01-03   2  102
2019-01-04   3  103
2019-01-05   4  104
2019-01-06   5  105
2019-01-07   6  106
2019-01-08   7  107
2019-01-09   8  108
2019-01-10   9  109
2019-01-11  10  110

or you can also do:

val2 <- 1
cbind(val = v, val2)

giving:

           val val2
2019-01-02   1    1
2019-01-03   2    1
2019-01-04   3    1
2019-01-05   4    1
2019-01-06   5    1
2019-01-07   6    1
2019-01-08   7    1
2019-01-09   8    1
2019-01-10   9    1
2019-01-11  10    1

ADDED

Actually this does work using the development version of zoo.

# install development version of zoo
install.packages("zoo", repos="http://R-Forge.R-project.org")

res <- cbind(val = v, val2 = "test")
str(res)

giving a character matrix as the data

‘zoo’ series from 2019-01-02 to 2019-01-11
  Data: chr [1:10, 1:2] "1" "2" "3" "4" "5" "6" "7" "8" "9" "10" "test" "test" ...
 - attr(*, "dimnames")=List of 2
  ..$ : NULL
  ..$ : chr [1:2] "val" "val2"
  Index:  Date[1:10], format: "2019-01-02" "2019-01-03" "2019-01-04" "2019-01-05" "2019-01-06" ...

which looks like this

> res
           val val2
2019-01-02 1   test
2019-01-03 2   test
2019-01-04 3   test
2019-01-05 4   test
2019-01-06 5   test
2019-01-07 6   test
2019-01-08 7   test
2019-01-09 8   test
2019-01-10 9   test
2019-01-11 10  test

Upvotes: 2

Denis
Denis

Reputation: 12087

So the proper way to bind an extra column to a univariate zoo series is to bind another univariate series to it with the same index as the original series. So in my case I had to do:

cbind(v, val2 = zoo("test", index(v))

Thank you @marcus for the tip. @markus, if you would like to put a better answer feel free to post your answer and I will remove this explanation so you get full credit for your answer.

Upvotes: 0

Related Questions