R function works on a separate column but does not apply
I have the following problem. I created this simple function to remove the last 2 non-NA values from a vector (xts). It works great.
library(xts)
last2na <- function(x) { x[which(is.na(lag(x,-2)))] <- NA; return(x) }
However, when I try to apply to a column of a matrix (xts), it does nothing with the matrix itself. But if I apply this function separately to each column, then it works.
For example, take the following matrix:
d <- xts(matrix(1:14, ncol=2), Sys.Date()+1:7)
d[5:7,1] <- NA
d[7,2] <- NA
If I applied a function to each column, for example 2nd:
last2na(d[,2])
I am getting the correct result (i.e. replacing the last non-NA value with the NA value). But if I use:
apply(d, 2, last2na)
then nothing happens. I am returning the original d matrix unchanged. I do not understand what the problem is.
Can someone please help me with this? many thanks
One way to see what's going on is to add print(str(x))
to your function last2na
. Or just replace it with str
:
str(d[,2])
# An ‘xts’ object on 2014-12-14/2014-12-20 containing:
# Data: int [1:7, 1] 8 9 10 11 12 13 NA
# Indexed by objects of class: [Date] TZ: UTC
# xts Attributes:
# NULL
Versus:
apply(d, 2, str)
# Named int [1:7] 1 2 3 4 NA NA NA
# - attr(*, "names")= chr [1:7] "2014-12-14" "2014-12-15" "2014-12-16" "2014-12-17" ...
# Named int [1:7] 8 9 10 11 12 13 NA
# - attr(*, "names")= chr [1:7] "2014-12-14" "2014-12-15" "2014-12-16" "2014-12-17" ...
# NULL
You can see that it apply
does not loop on columns xts
, but on simple integer vectors, which is what makes it last2na
unfortunate in its task.
Si transformation registered in ?apply
:
If X is not an array, but a class object with a non-empty dim value (such as a data frame), try to force it to the array via as.matrix if it is two-dimensional (such as a data frame) or via as.array
Essentially, he does apply(as.matrix(d), 2, last2na)
.
To figure out what went wrong. If you are looking for a solution, I am not an expert with objects xts
, but I noticed that it lag(d, -2)
works on the whole "matrix", so you can use this trick of adding a lag and then removing it:
d <- d + lag(d, -2) - lag(d, -2)
- where is the lag
NA
, adding will turn the values intoNA
- where the lag is not
NA
, addition, then subtraction of the value will have no effect.
It looks like apply cannot handle xts objects, and your function cannot handle matrix:
d <- as.matrix(d)
d
last2na(d[,2])
Here's a (inelegant, I admit) solution:
last2na_matrix <- function(x) {x[is.na(x[-1])] <- NA; x[is.na(x[-1])] <- NA; return(x) }
apply(d, 2, last2na_matrix)