Writing to dataframe in double for loop - r

I have a nested list (FCdat.pp.con[[x]][[y]]) in which seperate columns hold values of a matrix (for each x and nested y). Now I want to make the matrices by writing to dataframes.
However, I don't succeed in giving the matrices the correct name in a double for loop. At the moment, I only succeeded in making matrices with information about "x" but not with information about "y". Please help me out or suggest another method to do this.
for (x in 1:36){
for (y in 1:5){
cells <- c(0,
FCdat.pp.con[[x]][[y]]$A12,
FCdat.pp.con[[x]][[y]]$A13,
FCdat.pp.con[[x]][[y]]$A14,
FCdat.pp.con[[x]][[y]]$A21,0,
FCdat.pp.con[[x]][[y]]$A23,
FCdat.pp.con[[x]][[y]]$A24,
FCdat.pp.con[[x]][[y]]$A31,
FCdat.pp.con[[x]][[y]]$A32,
0,
FCdat.pp.con[[x]][[y]]$A34,
FCdat.pp.con[[x]][[y]]$A41,
FCdat.pp.con[[x]][[y]]$A42,
FCdat.pp.con[[x]][[y]]$A43,
0)
rnames <- c("ALG1","ALG2","ALG3","ALG4")
cnames <- c("ALG1","ALG2","ALG3","ALG4")
Ind.matr <- t(matrix(cells, nrow=4, ncol = 4))
dimnames(Ind.matr)=list(rnames, cnames)
assign(paste0("Indmatr", x), Ind.matr)
}
}

Add this before the loop begins: result <- lapply(1:36, function(.)vector("list",5))
Then replace assign(paste0("Indmatr", x), Ind.matr) with result[[x]][[y]] <- Ind.matr.

Related

Use of dim() in the lapply command

I have a list which contains again multiple lists of matrices of the dimensions 3834 1. So all values are basically stored in one column. Now I want to adjust the dimensions of the single matrices of each sublist, so that the new dimensions are 54 71.
Here is some code to reproduce sample data:
######################### create sample data ###########################
# create empty list
list1 <- list()
# fill the list with arrays/matrices
for (i in 1:10) {
list1[[i]] <- array(sample(1:100, 600, replace=T), dim= c(54*71,1))
}
# create the big list
big_list <- list()
for (i in 1:8) {
big_list[[paste0("list", i)]] <- list1
}
The goal can be achieved by using a for loop:
# adjust the dimensions of the matrices by using for loop
for (i in 1:length(big_list)) {
for (j in 1:length(big_list[[1]])) {
dim(big_list[[i]][[j]]) <- c(54,71)
}
}
I am sure that there is a more elegant way than using five lines for this, most likely by using lapply/apply/tapply etc. But I could not figure out how to place the dim() and c(54,71) properly in the command.
Anybody with a hint?
In R, the code
f(x) <- y
is equivalent to
x <- `f<-`(x, value = y)
With that in mind, you can use (nested) lapply with dim<-:
big_list <- lapply(
big_list,
function (lst) lapply(lst, `dim<-`, c(54L, 71L))
)
… and in principle you can omit the anonymous function — but whether that’s readable is debatable:
big_list <- lapply(big_list, lapply, `dim<-`, c(54L, 71L))
For what its worth, map_depth() from purrr is useful to dig into nested lists.
library(purrr)
map_depth(big_list, 2, matrix, nrow = 54, ncol = 71)
# or
map_depth(big_list, 2, `dim<-`, c(54L, 71L))

nested loop in r to correlate columns of df1 to columns of df2

I have two datasets with abundance data from groups of different species. Columns are species and rows are sites. The sites (rows) are identical between the two datasets and what i am trying to do is to correlate the columns of the first dataset to the columns of the second dataset in order to see if there is a positive or a negative correlation.
library(Hmisc)
rcorr(otu.table.filter$sp1,new6$spA, type="spearman"))$P
rcorr(otu.table.filter$sp1,new6$spA, type="spearman"))$r
the first will give me the p value of the relation between sp1 and spA and the second the r value
I initially created a loop that allowed me to check all species of the first dataframe with a single column of the second dataframe. Needless to say if I was to make this work I would have to repeat the process a few hundred times.
My simple loop for one column of df1(new6) against all columns of df2(otu.table.filter)
pvalues = list()
for(i in 1:ncol(otu.table.filter)) {
pvalues[[i]] <-(rcorr(otu.table.filter[ , i], new6$Total, type="spearman"))$P
}
rvalues = list()
for(i in 1:ncol(otu.table.filter)) {
rvalues[[i]] <-(rcorr(otu.table.filter[ , i], new6$Total, type="spearman"))$r
}
p<-NULL
for(i in 1:length(pvalues)){
tmp <-print(pvalues[[i]][2])
p <- rbind(p, tmp)
}
r<-NULL
for(i in 1:length(rvalues)){
tmp <-print(rvalues[[i]][2])
r <- rbind(r, tmp)
}
fdr<-as.matrix(p.adjust(p, method = "fdr", n = length(p)))
sprman<-cbind(r,p,fdr)
and using the above as a starting point I tried to create a nested loop that each time would examine a column of df1 vs all columns of df2 and then it would proceed to the second column of df1 against all columns of df2 etc etc
but here i am a bit lost and i could not find an answer for a solution in r
I would assume that the pvalues output should be a list of
pvalues[[i]][[j]]
and similarly the rvalues output
rvalues[[i]][[j]]
but I am a bit lost and I dont know how to do that as I tried
pvalues = list()
rvalues = list()
for (j in 1:7){
for(i in 1:ncol(otu.table.filter)) {
pvalues[[i]][[j]] <-(rcorr(otu.table.filter[ , i], new7[,j], type="spearman"))$P
}
for(i in 1:ncol(otu.table.filter)) {
rvalues[[i]][[j]] <-(rcorr(otu.table.filter[ , i], new7[,j], type="spearman"))$r
}
}
but I cannot make it work cause I am not sure how to direct the output in the lists and then i would also appreciate if someone could help me with the next part which would be to extract for each comparison the p and r value and apply the fdr function (similar to what i did with my simple loop)
here is a subset of my two dataframes
Here a small demo. Let's assume two matrices x and y with a sample size n. Then correlation and approximate p-values can be estimated as:
n <- 100
x <- matrix(rnorm(10 * n), nrow = n)
y <- matrix(rnorm(5 * n), nrow = n)
## correlation matrix
r <- cor(x, y, method = "spearman")
## p-values
pval <- function(r, n) 2 * (1 - pt(abs(r)/sqrt((1 - r^2)/(n - 2)), n - 2))
pval(r, n)
## for comparison
cor.test(x[,1], y[,1], method = "spearman", exact = FALSE)
More details can be found here: https://stats.stackexchange.com/questions/312216/spearman-correlation-significancy-test
Edit
And finally a loop with cor.test:
## for comparison
p <- matrix(NA, nrow = ncol(x), ncol=ncol(y))
for (i in 1:ncol(x)) {
for (j in 1:ncol(y)) {
p[i, j] <- cor.test(x[,i], y[,j], method = "spearman")$p.value
}
}
p
The values differ a somewhat, because the first uses the t-approximation then the second the "exact AS 89 algorithm" of cor.test.

apply list of indices to list of dataframes

I need to apply a list of indices to a list of dataframes with a one on one mapping. First element of the list of indices goes to the first dataframe only and so on. List of indices applies to the rows in the dataframes.
And a list of complementary dataframes needs to created by selecting rows not mentioned in the indices list.
Here is some sample data:
set.seed(1)
A <- data.frame(matrix(rnorm(40,0,1), nrow = 10))
B <- data.frame(matrix(rnorm(40,2,3), nrow = 10))
C <- data.frame(matrix(rnorm(40,3,4), nrow = 10))
dflis <- list(A,B,C)
# Create a sample row index
ix <- lapply(lapply(dflis,nrow), sample, size = 6)
So far I have managed this working but ugly looking code:
dflis.train <- lapply(seq_along(dflis), function(x) dflis[[x]][ix[[x]],])
dflis.test <- lapply(seq_along(dflis), function(x) dflis[[x]][-ix[[x]],])
Can someone suggest something better, more elegant?
Use Map/mapply instead of the univariate lapply, so that you can iterate over both objects and apply a function, like:
Map(function(d,r) d[r,], dflis, ix)
Or if you want to be fancy:
Map(`[`, dflis, ix, TRUE)
Matches your requested answer.
identical(
Map(function(d,r) d[r,], dflis, ix),
lapply(seq_along(dflis), function(x) dflis[[x]][ix[[x]],])
)
#[1] TRUE

Convert list of tables to a list of matrices

I have a list of table list_table_Tanzania which I want to conver into a list of matrices list_matrix_Tanzania. I tried to run this for loop function but I got only one output.
for (i in 1:length(list_table_Tanzania)) {
list_matrix_Tanzania<-as.matrix(list_table_Tanzania[[i]], rownames.force = NA)
}
Does somebody know how could I get the same number of matrices of the number of tables in my list?
You are overwriting the value of list_matrix_Tanzania in each iteration.
Try with lapply
list_matrix_Tanzania <- lapply(list_table_Tanzania, as.matrix, rownames.force = NA)
Doing it with a for loop is also possible, you first have to initialise your list by list_matrix_Tanzania <- vector("list", length(list_table_Tanzania) and then in the for loop assign the result of the ith iteration to list_matrix_Tanzania[[i]]
Edit To remove some columns from the lapply result, you can modify it to something like
list_matrix_Tanzania <- lapply(list_table_Tanzania, function(d) {
result <- as.matrix(d, rownames.force = NA)
v <- 1:2 # Replace this with the indices of the columns you wish to remove
result[, -v]
})

R programming - from a matrix containing points to neighbours list

I know there is a R method that enables programmers to convert neighbours list to a matrix.
I am trying to do the opposite process; is there anyway that I can convert a matrix that contains x and y coordinates of points to a neighbours list?
thank you
PS: I tried the following:
require(spdep)
mat2listw(myMatrix)$neighbours
but this is causing a problem since myMatrix has to be a square matrix...in my case my matrix is 11*2, which is not square.
You can try the following.
# need indices. Use Names or numeric index
rr <- if(is.null(rownames(myMatrix))) seq(nrow(myMatrix)) else rownames(myMatrix)
cc <- if(is.null(colnames(myMatrix))) seq(ncol(myMatrix)) else colnames(myMatrix)
inds <- as.matrix( expand.grid(X=rr, Y=cc) )
## as a data.frame
data.frame(inds, Dist=myMatrix[inds])
## as a list
ret <- apply(inds, 1, function(i) list(c(i, Dist=myMatrix[rbind(i)])))
# possibly unlist if needed
unlist(ret, recursive=FALSE)
Sample Data
set.seed(1)
myMatrix <- matrix(sample(8, 22, TRUE), ncol=2, dimnames=list(LETTERS[1:11], letters[1:2]))
myMatrix

Resources