Reputation: 37121
I have a long-format data.frame
which I would like to use to construct a wide-format zoo
series.
The data.frame
looks like:
Date Label Value
1 2015-03-21 A 1
2 2015-03-22 B 6
3 2015-03-22 A 2
4 2015-03-23 A 7
5 2015-03-23 B 5
...
For example:
d <- data.frame(
Date = c(Sys.Date() - 2, Sys.Date() - 1, Sys.Date() -1, Sys.Date(), Sys.Date()),
Label = c("A", "B", "A", "A", "B"),
Value = c(1, 6, 2, 7, 5))
My result should be a zoo
that looks like:
A B ...
2015-03-21 1 NA ...
2015-03-22 2 6 ...
2015-03-23 7 5 ...
...
I have managed to achieve this using:
f <- function(x) {
zoo(x$Value, order.by = x$Date)
}
do.call(merge.zoo, by(d, factor(d$Label), f))
where d
is the data.frame
.
However, when d
only contains one Label
, it drops the column name somewhere:
2015-03-21 2015-03-22 2015-03-23
1 2 7
and names(d)
gives NULL
.
How can I maintain the column names, even when the output zoo
is univariate?
Upvotes: 1
Views: 706
Reputation: 37121
The problem is that merge.zoo
will drop names for a univariate zoo
by default.
This behaviour can be overridden by passing drop = F
to the args list. We can use a partial function application of merge.zoo
to achieve this when using do.call
:
f <- function(x) {
zoo(x$Value, order.by = x$Date)
}
s <- do.call(partial(merge.zoo, drop = F), by(d, factor(d$Label), f))
or without partial:
s <- do.call(merge.zoo, append(by(d, factor(d$Label), f), list(drop = F)))
For d <- d[d$Label == "A", ]
this gives:
A
2015-03-21 1
2015-03-22 2
2015-03-23 7
Note that the pryr
package is required for partial function application.
Upvotes: 0
Reputation: 270348
Use the split=
argument of read.zoo
to split on the second column:
library(zoo)
read.zoo(d, split = 2)
giving:
A B
2015-03-21 1 NA
2015-03-22 2 6
2015-03-23 7 5
Upvotes: 3