list conversion of jsonlite in R - r

I would like to have a list of matrices within R imported from a json file using jsonlite.
A <- matrix(rnorm(100),10,10)
B <- matrix(rnorm(100),10,10)
C <- matrix(rnorm(100),10,10)
l <- list(A,B,C)
import_l <- fromJSON(toJSON(l),simplifyMatrix = FALSE)
the above code doesnt work since it is R internally a list of list of numerics. However, I would like to have my list of A,B,C back, i.e. l. Is there a way to achieve getting back the correct list of matrices using jsonlite?

The issue here is that a column matrix and an unnamed list look the same if converted to JSON:
toJSON(list(1, 2, 3))
## [[1],[2],[3]]
toJSON(matrix(c(1, 2, 3), ncol = 1))
## [[1],[2],[3]]
However, a named list looks different:
toJSON(list(A = 1, B = 2, C = 3))
## {"A":[1],"B":[2],"C":[3]}
If you use a named list in your example, fromJSON() does indeed reproduce the original list:
l <- list(A = A, B = B, C = C)
all.equal(fromJSON(toJSON(l)), l, tol = 1e-4)
## [1] TRUE
If this is not possible - for example because you don't create the JSON file yourself, but get it as an input - you can also convert the result you get with fromJSON():
l <- list(A, B, C)
import_l <- fromJSON(toJSON(l))
l2 <- lapply(1:3, function(i) import_l[i, , ])
all.equal(l2, l, tol = 1e-4)
## [1] TRUE

Related

rev() in r and how to apply it to a list using loops

I have a list of say {a,b,c,d,...} and each element, a,b,c,d, ... are data.table that I need to reverse the order of, however, for the data.table I only want to rev() all of it except the first column, as it is an ID. I tried using loops to do it but it returned
Error in `[<-.data.table`(`*tmp*`, , -1, value = list(code_a = c("a", :
Item 1 of column numbers in j is -1 which is outside range [1,ncol=4]. Use column names instead in j to add new columns.
Example:
a <- c("a","b","c","d","e","f")
b <- 1:6
c <- c("F","E","D","C","B","A")
d <- 10:15
dt1 <- data.table("ID" = b, "code_a" = a)
dt2 <- data.table("ID" = b, "code_c" = c)
dt3 <- data.table("ID" = b, "code_d" = d)
dt <- list(dt1,dt2,dt3)
rev_dt <- rev(dt)
merged_list <- list()
rev_merged_list <- list()
rev_merged_list <- Reduce(merge, rev_dt, accumulate = TRUE)
merged_list <- rev_merged_list
merged_list <- rev(merged_list)
for(z in 1:length(dt)){
merged_list[[z]][,-1] = rev(merged_list[[z]][,-1])
}
More Information:
The for loop here is supposed to be:
- for z from 1 to the length of dt
- the merged_list element z (which with double square brackets) should be a data.table
- where the data does not include the first column
- should be assigned to the rev of the same element z, where the first column is also excluded
Does this logic hold for the above loop? I am unsure what is wrong!
Expected Output:
output_ <- list()
a_ <- data.table("ID" = b, "code_a" = a, "code_c" = c, "code_d" = d)
b_ <- data.table("ID" = b, "code_c" = c, "code_d" = d)
c_ <- data.table("ID" = b, "code_d" = d)
output_[[1]] <- a_
output_[[2]] <- b_
output_[[3]] <- c_
output_
I was told yesterday that the merge above i can specify a right hand merge, however in doing so, I need to specify a by = "ID" in the merge, but I am unsure what is the x and y values in the case of merging multiple sets of data.
I am also under the impression that lapply() can do the same thing instead of loop, but I am unsure in this case how might I achieved that. Thanks~
We can use setcolorder
for(i in seq_along(merged_list)){
setcolorder(merged_list[[i]],
c(names(merged_list[[i]])[1], rev(names(merged_list[[i]])[-1])))
}
all.equal(merged_list, output_, check.attributes = FALSE)
#[1] TRUE

Variance of a List of Arrays

Suppose x is a list of arrays.
a <- array(1,c(2,3,4));
b <- array(2,c(2,3,4));
c <- array(3,c(2,3,4));
x <- list(a=a,b=b,c=c)
My desired output is the following array:
array(var(c(1,2,3)),c(2,3,4))
This is quietly same as the following page, but change the sum to the variance.
Ref: Sum a list of arrays
Edit for comments of #akrun
Thank you #akrun.
His answer is the following;
apply(
array(unlist(x),append( dim(x[[1]]), length(x) ) ),
1:length(dim(x[[1]])),
var
)
where x is the following list of arrays:
a <- array(1,c(2,3,4));
b <- array(2,c(2,3,4));
c <- array(3,c(2,3,4));
d <- array(4,c(2,3,4));
x <- list(a=a,b=b,c=c,d=d)
One option would be to unlist the list, create an array and use apply to get the variance
apply(array(unlist(x), c(2, 3, 4, 3)), 1:3, var)

fminsearch on a single variable

Using R's help page example on fminsearch as a starting point:
# Rosenbrock function
rosena <- function(x, a) 100*(x[2]-x[1]^2)^2 + (a-x[1])^2 # min: (a, a^2)
fminsearch(rosena, c(-1.2, 1), a = sqrt(2))
# x = (1.414214 2.000010) , fval = 1.239435e-11
I want to evaluate something like this but with only one variable such as:
rosena <- function(x, a) 100*(x[1]-x[1]^2)^2 + (a-x[1])^2
but when I run
fminsearch(rosena, c(1), a = sqrt(2))
It gives the error: Error in X[2:d1, ] : incorrect number of dimensions
fminsearch seems to want a vector of length greater than or equal to 2, but no less, however for this example, the vector requires length 1
Note: fminsearch is in the "pracma" package
It looks like a bug in the pracma package.
The anms function is dropping a dimension upon a subscript, relevant excerpts:
d <- length(x0) # i.e. 1
d1 <- d + 1 # i.e. 2
...
X <- matrix(0, nrow = d1, ncol = d)
...
X <- X[o, ] # could put drop = FALSE here
I think you should post a bug with the author of the package.

naming and rbinding all elements (dfs, matrices, vectors, etc.) from lists of list

I have a list with lists like this:
# output from a package function
A <- list(a = matrix(1:9,ncol=3),
b = matrix(1:8,ncol=4),
c = 1.5)
B <- list(a = matrix(11:19,ncol=3),
b = matrix(11:18,ncol=4),
c = 2.5)
# list with all outputs (from loaded=lapply(filenames, function(x) get(load(x))) )
superlist <- list(A, B))
What I would like to do is first add the name of each list item (A, B) to all second order list elements. For example B would become:
B <- list(a = cbind(matrix(11:19,ncol=3),c("B","B","B")),
b = cbind(matrix(11:18,ncol=4),c("B","B")),
c = c(2.5,"B"))
Then, the aim is to rbind all matrices, values or dataframes (a,b,c) with the same name together, so that I would have:
superlist <- list(a = rbind(cbind(matrix(1:9,ncol=3),c("A","A","A")),cbind(matrix(11:19,ncol=3),c("B","B","B"))),
b = rbind(cbind(matrix(1:8,ncol=4),c("A","A")),cbind(matrix(11:18,ncol=4),c("B","B"))),
c = rbind(c(1.5,"A"),c(2.5,"B")))
For the rbinding, the best I got is this (from rbind all dataframes in a list of lists by name):
do.call("rbind",lapply(superlist ,function(x) x[["a"]]))
However, it only does it for one list element (and I have more than 20). I know that I can write a loop, but as I will be using the function often I would like to know how to do this nicer.
I am aware that there are multiple questions asked about this, but none of them has exactly the same problem (for example, some only have data frames as list of list elements, sometimes all of the same size). So although certain questions provided a bit of help, none truly gave me enough information to resolve my problem.
rbind dataframes in a list of lists # groups by the second list, not the first
Convert a list of data frames into one data frame # only one list
rbinding a list of lists of dataframes based on nested order
...
Thank you
I think can utilize the function proposed in this answer. It reverses the list structure i.e. groups by inner list. An example:
# output from a package function
A <- list(a = matrix(1:9,ncol=3),
b = matrix(1:8,ncol=4),
c = 1.5)
B <- list(a = matrix(11:19,ncol=3),
b = matrix(11:18,ncol=4),
c = 2.5)
# list with all outputs (from loaded=lapply(filenames, function(x) get(load(x))) )
superlist <- list(A, B)
################### your code above ##############
## the function from the linked answer
fun <- function(ll) {
nms <- unique(unlist(lapply(ll, function(X) names(X))))
ll <- lapply(ll, function(X) setNames(X[nms], nms))
ll <- apply(do.call(rbind, ll), 2, as.list)
lapply(ll, function(X) X[!sapply(X, is.null)])
}
## apply the function to your list
insideout <- fun(superlist)
## rbind the components together
lapply(insideout, function(x) do.call(rbind, x))
Is this what you intended to do?

Creating block matrix via loop

I'm trying to create a block matrix using a loop in R, which depend on some variable I call T. The two matrices used to construct the block matrix could look like this:
A=matrix(c(1,0.3,0.3,1.5),nrow=2)
B=matrix(c(0.5,0.3,0.3,1.5),nrow=2)
So depending on what i set T to, I need different results. For T=2:
C=rbind(cbind(A,B),cbind(B,A))
For T=3:
C=rbind(cbind(A,B,B),cbind(B,A,B),cbind(B,B,A))
For T=5:
C=rbind(cbind(A,B,B,B,B),cbind(B,A,B,B,B),cbind(B,B,A,B,B),cbind(B,B,B,A,B),cbind(B,B,B,B,A))
So basically, I'm just trying to create a loop or something similar, where I can just specify my T and it will create the block matrix for me depending on T.
Thanks
You can do that:
N <- nrow(A)
C <- matrix(NA,N*T,N*T)
for (i in 1:T){
for (j in 1:T){
if (i == j)
C[(i-1)*N+1:N, (j-1)*N+1:N] <- A
else
C[(i-1)*N+1:N, (j-1)*N+1:N] <- B
}
}
From your explanation I suppose that you want single A and T-1 Bs in your final matrix.
If that is correct then here is a quick try using the permn function from the combinat library. All I am doing is generating the expression using the permutation and then evaluating it.
A = matrix(c(1,0.3,0.3,1.5),nrow=2)
B = matrix(c(0.5,0.3,0.3,1.5),nrow=2)
T = 5
x = c("A", rep("B",T-1))
perms = unique(permn(x)) #permn generates non-unique permutations
perms = lapply(perms, function(xx) {xx=paste(xx,collapse=","); xx=paste("cbind(",xx,")")})
perms = paste(perms, collapse=",")
perms = paste("C = rbind(",perms,")",collapse=",")
eval(parse(text=perms))
With the blockmatrix package this is pretty straightforward.
library(blockmatrix)
# create toy matrices (block matrix elements)
# with values which makes it easier to track them in the block matrix in the example here
A <- matrix("a", nrow = 2, ncol = 2)
B <- matrix("b", nrow = 2, ncol = 2)
# function for creating the block matrix
# n: number of repeating blocks in each dimension
# (I use n instead of T, to avoid confusion with T as in TRUE)
# m_list: the two matrices in a list
block <- function(n, m_list){
# create a 'layout matrix' of the block matrix elements
m <- matrix("B", nrow = n, ncol = n)
diag(m) <- "A"
# build block matrix
as.matrix(blockmatrix(dim = dim(m_list[[1]]), value = m, list = m_list))
}
# try with different n
block(n = 2, m_list = list(A = A, B = B))
block(n = 3, m_list = list(A = A, B = B))
block(n = 5, m_list = list(A = A, B = B))

Resources