Reputation: 397
Let´s say that my data has the following structure:
structure(list(Year = c(2000, 2000, 2000, 2000, 2000, 2000, 2000,
2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000,
2000, 2000, 2001, 2001, 2001, 2001), Month = c(1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), Day = c(1,
1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 1, 1,
1, 1), FivMin = c(1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3,
4, 1, 2, 3, 4, 1, 2, 3, 4), A = c(1, 2, 3, 0, 1, 5, 3, 4, 1,
0, 3, 1, 0, 2, 3, 0, 1, 2, 0, 9, 1, 2, 3, 0), B = c(2, 3, 4,
1, 2, 3, 0, 1, 2, 1, 4, -2, 2, 1, 0, 2, 2, 3, -1, 1, 2, 3, 4,
1), C = c(3, 0, 1, 2, 3, 4, 1, 9, 3, 7, 1, 2, 3, 4, 1, 2, 3,
4, 1, 2, 3, 0, 1, 2), D = c(4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2,
3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3)), row.names = c(NA, -24L
), class = c("tbl_df", "tbl", "data.frame"))
My idea is use the crossproduct
comand every day. In order to do that I wrote the following code:
res <- lapply(split(data, data[c("Year","Month","Day")]),
function(x) tcrossprod(t(x[c("A","B","C","D")])))
Final<-do.call(rbind, lapply(res, diag))
The output of Final is:
A B C D
2000.1.1 14 30 14 30
2001.1.1 14 30 14 30
2000.1.2 51 14 107 30
2001.1.2 0 0 0 0
2000.1.3 11 25 63 30
2001.1.3 0 0 0 0
2000.1.4 13 9 30 30
2001.1.4 0 0 0 0
2000.1.5 86 15 30 30
2001.1.5 0 0 0 0
What I need is a time serie (matrix or df object) formed by the diagonals calculated with crossproduct
, It means my desired time serie would be
A B C D
2000.1.1 14 30 14 30
2000.1.2 51 14 107 30
2000.1.3 11 25 63 30
2000.1.4 13 9 30 30
2000.1.5 86 15 30 30
2001.1.1 14 30 14 30
What would be the changes in my original code. I think that i could replace the split
command by grouped_by
but it did not work.
Upvotes: 2
Views: 60
Reputation: 2949
As the split makes data frame into list, it creates 0 rows as well. Just remove those zero rows and try.
ls<- split(data, data[c("Year","Month","Day")])
ls<- ls[sapply(ls, nrow)>0]
res <- lapply(ls, function(x) tcrossprod(t(x[c("A","B","C","D")])))
Final<-do.call(rbind, lapply(res, diag))
Final <- Final[ order(row.names(Final)), ]
Final
Output:
A B C D
2000.1.1 14 30 14 30
2000.1.2 51 14 107 30
2000.1.3 11 25 63 30
2000.1.4 13 9 30 30
2000.1.5 86 15 30 30
2001.1.1 14 30 14 30
Upvotes: 1