I was wondering how to modify my mapply
call to avoid getting: Error: $ operator is invalid for atomic vectors
after my last line of code?
Note: the use of matrix(c(1, .1, 2, .2), nrow = 2)
is just for simplicity.
My expected output is:
$Trus
[,1] [,2]
[1,] 1.0 2.0
[2,] 0.1 0.2
$Yu_Chen
[,1] [,2]
[1,] 1.0 2.0
[2,] 0.1 0.2
My reproducible code is:
ctlist <- function(mm, cont=FALSE, pos=1, outcom=1){
mm <- mm[[1]]
mm[mm$control==cont & mm$post == pos & mm$outcome == outcom, , drop = FALSE]
}
#=========
dinter <- function(m, pos, outcom){
clist <- ctlist(mm=m, cont=TRUE, pos = pos, outcom = outcom)
tlist <- ctlist(mm=m, cont=FALSE, pos = pos, outcom = outcom)
matrix(c(1, .1, 2, .2), nrow = 2) # For simplicity
}
#=========
L1 = list(Trus = data.frame(control=c(T,F), post=c(1,1), outcome=c(1,1), time=c(2,2)),
Yu_Chen = data.frame(control=c(F,F,T,T), post=c(1,2,1,2), outcome=c(1,1,1,1), time=c(1,2,1,2)) )
#=========
G <- function(m){
input <- rev(expand.grid(outcom = seq_len(max(m$outcom, na.rm = TRUE)), pos = seq_len(max(m$post, na.rm = TRUE))))
mapply(dinter, m=m, input$pos, input$outcom)
}
#=========
setNames(lapply(L1, G), names(L1))
#Error: $ operator is invalid for atomic vectors
#Called from: ctlist(mm = m, cont = TRUE, pos = pos, outcom = outcom)
There are couple of issues in the function ctlist
mm <- mm[[1]]
updates the 'mm' to a vector
by extracting the first column. Now, it doesn't have any dim attributes. So, if we do the next line, it won't work because those columns are not present as it is a vector
mm[mm$control==cont & mm$post == pos & mm$outcome == outcom, , drop = FALSE]
Now, checking the dinter
, it is unclear, why the OP created the clist
and tlist
and then a matrix
out of the blue as expected. It can be simplified with
ctlist <- function(mm, cont=FALSE, pos=1, outcom=1){
mm[mm$control==cont & mm$post == pos & mm$outcome == outcom, , drop = FALSE]
}
lapply(L1, function(m) {
input <- rev(expand.grid(outcom = seq_len(max(m$outcom,
na.rm = TRUE)), pos = seq_len(max(m$post, na.rm = TRUE))))
dinter(m, pos = 1, outcom = 1)
})
#$Trus
# [,1] [,2]
#[1,] 1.0 2.0
#[2,] 0.1 0.2
#$Yu_Chen
# [,1] [,2]
#[1,] 1.0 2.0
#[2,] 0.1 0.2
If we are applying the dinter
on each element of 'input$pos', 'input$outcom', then the m
should be the same. In the OP's code, 'm' is also an input to mapply/Map
. As 'm' is a data.frame, the unit is a column. So, it loops over the columns, while the loop for input$pos and input$outcom is a single element (creating an issue in the 'ctlist' function which expects 'mm' as a data.frame along with the fact that length of input$pos and the number of columns of 'mm' differ)
lapply(L1, function(m) {
input <- rev(expand.grid(outcom = seq_len(max(m$outcom, na.rm = TRUE)), pos = seq_len(max(m$post, na.rm = TRUE))))
Map(dinter, MoreArgs = list(m = m), pos = input$pos, outcom = input$outcom)
})
#$Trus
#$Trus[[1]]
# [,1] [,2]
#[1,] 1.0 2.0
#[2,] 0.1 0.2
#$Yu_Chen
#$Yu_Chen[[1]]
# [,1] [,2]
#[1,] 1.0 2.0
#[2,] 0.1 0.2
#$Yu_Chen[[2]]
# [,1] [,2]
#[1,] 1.0 2.0
#[2,] 0.1 0.2
If we want to flatten the list, use c
with do.call
do.call(c, lapply(L1, function(m) {
input <- rev(expand.grid(outcom = seq_len(max(m$outcom,
na.rm = TRUE)), pos = seq_len(max(m$post, na.rm = TRUE))))
Map(dinter, MoreArgs = list(m = m), pos = input$pos,
outcom = input$outcom)
}))