Search code examples
rloopsxts

How do I extract dates based on values of columns of a time series?


Suppose I have:

A <- c(1,0,0,0)
B <- c(0,1,0,0)
C <- c(0,0,1,0)
D <- c(0,0,0,1)
data <- xts(cbind(A,B,C,D),order.by = as.Date(1:4))

Then I get...

           A B C D
1970-01-02 1 0 0 0
1970-01-03 0 1 0 0
1970-01-04 0 0 1 0
1970-01-05 0 0 0 1

I would like to extract the dates for each column where the value is 1. So I want to see something like this...

A "1970-01-02"
B "1970-01-03"
C "1970-01-04"
D "1970-01-05"

Here's the manual way of getting the answer. So I basically want to run a loop that can do this...

index(data$A[data$A==1])
index(data$B[data$B==1])
index(data$C[data$C==1])
index(data$D[data$D==1])

Solution

  • If for a particular row there are multiple 1's and you want to return the index only once for that row, we can use rowSums and subset the index

    zoo::index(data)[rowSums(data == 1) > 0]
    #[1] "1970-01-02" "1970-01-03" "1970-01-04" "1970-01-05"
    

    If we want index value for each 1, we can use which with arr.ind = TRUE

    zoo::index(data)[which(data == 1, arr.ind = TRUE)[, 1]]
    

    To get both column name as well as index, we can reuse the matrix from which

    mat <- which(data == 1, arr.ind = TRUE)
    data.frame(index = zoo::index(data)[mat[, 1]], column = colnames(data)[mat[,2]])
    
    #       index column
    #1 1970-01-02      A
    #2 1970-01-03      B
    #3 1970-01-04      C
    #4 1970-01-05      D