Rename subtitles of a list using a loop - r

I do have to rename sublist titles within a main matrix list called l1. Each Name(n) is related to a value as a character string. Here is my code :
names(l1)[1] <- Name1
names(l1)[2] <- Name2
names(l1)[3] <- Name3
names(l1)[4] <- Name4
## ...
names(l1)[43] <- Name43
As you can see, I have 43 sublists. Is there a way do do that using an automated loop like for (i in 1:43) or something ? I tried to perform a loop but I am a beginner and that's very hard for now.
Edit : I would like to rename the elements of my list without having to type 43 lines manually. Here is the first three elements of my list :
str(l1)
List of 43
$ XXX : num [1:640, 1:3] -0.83 -0.925 -0.623 -0.191 0.155 ...
..- attr(*, "dimnames")=List of 2
.. ..$ : NULL
.. ..$ : chr [1:3] "EV_BICYCLE" "HW_DISTANCE" "NO_ASSETS"
$ XXX : num [1:640, 1:2] -0.159 0.485 -0.686 -0.245 -3.361 ...
..- attr(*, "dimnames")=List of 2
.. ..$ : NULL
.. ..$ : chr [1:2] "HOME_OWN" "METRO_DISTANCE"
$ XXX : num [1:640, 1:3] -0.79 1.15 0.224 0.388 -1.571 ...
..- attr(*, "dimnames")=List of 2
.. ..$ : NULL
.. ..$ : chr [1:3] "BICYCLE" "HOME_OWN_SC" "POP_SC"
That is to say, I would like to replace the 43 XXX by Name1, Name2 ... to Name43

Try
names(l1) <- unlist(mget(ls(pattern="^Nom_F")))
str(l1, list.len=2)
#List of 3
# $ Accessibility : int [1:5, 1:5] 10 10 3 9 7 6 8 2 7 8 ...
# ..- attr(*, "dimnames")=List of 2
# .. ..$ : NULL
# .. ..$ : chr [1:5] "A" "B" "C" "D" ...
# $ Access : int [1:5, 1:5] 6 4 10 5 9 8 9 4 7 1 ...
#..- attr(*, "dimnames")=List of 2
# .. ..$ : NULL
# .. ..$ : chr [1:5] "A" "B" "C" "D" ...
Instead of creating separate objects, you could create a vector of real titles. For example
v1 <- LETTERS[1:3]
names(l1) <- v1
data
set.seed(42)
l1 <- setNames(lapply(1:3, function(x)
matrix(sample(1:10, 5*5, replace=TRUE), ncol=5,
dimnames=list(NULL, LETTERS[1:5]))), rep('XXX',3))
Nom_F1 <- "Accessibility"
Nom_F2 <- "Access"
Nom_F3 <- "Poverty_and_SC"

Related

Extract values and attributes from a list and convert them into a dataframe in R

I got the following list for my model:
List of 9
$ phi : num [1:5, 1:1500] 1.8e-04 1.8e-04 1.8e-04 1.8e-04 1.8e-04 ...
..- attr(*, "dimnames")=List of 2
.. ..$ : chr [1:5] "t_1" "t_2" "t_3" "t_4" ...
.. ..$ : chr [1:1500] "word1" "word2" "word3" "word4" ...
$ theta : num [1:500, 1:5] 0.1234 0.4567 0.01234 0.04567 0.02345 ...
..- attr(*, "dimnames")=List of 2
.. ..$ : chr [1:500] "1" "2" "3" "4" ...
.. ..$ : chr [1:5] "t_1" "t_2" "t_3" "t_4" ...
$ gamma : num [1:5, 1:1500] 0.20 0.70 0.10 0.1 0.11 ...
..- attr(*, "dimnames")=List of 2
.. ..$ : chr [1:5] "t_1" "t_2" "t_3" "t_4" ...
.. ..$ : chr [1:1500] "word1" "word2" "word3" "word4" ...
$ data :Formal class 'dgCMatrix' [package "Matrix"] with 6 slots
.. ..# i : int [1:10000] 1234 6789 2233 1367 1123 1123 145 145 156 1325 ...
.. ..# p : int [1:1500] 0 1 2 3 4 5 6 7 8 9 ...
.. ..# Dim : int [1:2] 1234 1500
.. ..# Dimnames:List of 2
.. .. ..$ : chr [1:500] "1" "2" "3" "4" ...
.. .. ..$ : chr [1:1500] "word1" "word2" "word3" "word4" ...
.. ..# x : num [1:100000] 1 1 1 1 1 1 1 1 1 1 ...
.. ..# factors : list()
$ alpha : Named num [1:5] 0.1 0.1 0.1 0.1 ...
..- attr(*, "names")= chr [1:5] "t_1" "t_2" "t_3" "t_4" ...
$ beta : Named num [1:1500] 0.01 0.01 0.01 0.01 0.01 0.01 0.01 0.01 0.01 0.01 ...
..- attr(*, "names")= chr [1:1500] "word1" "word2" "word3" "word4"
Is there a way of how to select $theta and all its attributes and save them as a data frame? In other words, I want to extract this part from the list:
$ theta : num [1:500, 1:5] 0.1234 0.4567 0.01234 0.04567 0.02345 ...
..- attr(*, "dimnames")=List of 2
.. ..$ : chr [1:500] "1" "2" "3" "4" ...
.. ..$ : chr [1:5] "t_1" "t_2" "t_3" "t_4" ...
and have a dataframe that looks like this (the column order does not matter):
Theta | var1 | var2 |
0.1234 | 1 | t_1 |
0.4567 | 2 | t_2 |
0.01234| 3 | t_3 |
I have tried lapply and many other suggestions that I found in terms of list extraction but failed to extract the part shown above.
Thanks a lot!
As already metioned in comments, you can easily access $theta with list subsetting either model$theta or model[['theta']].
$theta is a numeric matrix 500 x 5. To convert it into desirable format just melt it:
theta_matrix = model$theta
theta_df = reshape2::melt(theta_matrix, value.name = "Theta")
Note that theta is a 500 x 5 numeric matrix, so the data frame will have 500 rows and 5 columns named t_1, t_2, t_3, t_4 and t_5 - it won't be a 3 - row data frame as in your expected output.
Assuming your list is called my_list, here's how you get theta as a data frame:
as.data.frame(my_list$theta)
Or perhaps
setNames(as.data.frame(my_list$theta), attr(my_list$theta, "dimnames")[[2]])

How can I pass a list of names to list.select?

Assume I want to use list.select function from rlist package to select two fields.
x <- list(p1 = list(type='A',score=list(c1=10,c2=8)),
p2 = list(type='B',score=list(c1=9,c2=9)),
p3 = list(type='B',score=list(c1=9,c2=7)))
rather than using this syntax:
list.select(x, type, score)
I want to use something list this, but it doesn't work:
param <- c("type", "score")
list.select(x, param)
Not sure how to do it using list.select, but here is a purrr solution:
library(purrr)
param <- c("type", "score")
map(x, `[`, param)
this obviously also works with lapply:
lapply(x, `[`, param)
but if you have a deeper nested list of lists, use modify_depth:
modify_depth(x, 1, `[`, param)
the .depth argument can be adjusted to go deeper down the hierarchy.
Output:
$p1
$p1$type
[1] "A"
$p1$score
$p1$score$c1
[1] 10
$p1$score$c2
[1] 8
$p2
$p2$type
[1] "B"
$p2$score
$p2$score$c1
[1] 9
$p2$score$c2
[1] 9
$p3
$p3$type
[1] "B"
$p3$score
$p3$score$c1
[1] 9
$p3$score$c2
[1] 7
This is a hackish way using eval(parse(.)) but the result is not identical to your solution. The pieces are there, though.
> str(list.select(x, do.call(c, sapply(param, FUN = function(x) eval(parse(text = x))))))
List of 3
$ p1:List of 1
..$ :List of 3
.. ..$ type : chr "A"
.. ..$ score.c1: num 10
.. ..$ score.c2: num 8
$ p2:List of 1
..$ :List of 3
.. ..$ type : chr "B"
.. ..$ score.c1: num 9
.. ..$ score.c2: num 9
$ p3:List of 1
..$ :List of 3
.. ..$ type : chr "B"
.. ..$ score.c1: num 9
.. ..$ score.c2: num 7
> str(list.select(x, type, score))
List of 3
$ p1:List of 2
..$ type : chr "A"
..$ score:List of 2
.. ..$ c1: num 10
.. ..$ c2: num 8
$ p2:List of 2
..$ type : chr "B"
..$ score:List of 2
.. ..$ c1: num 9
.. ..$ c2: num 9
$ p3:List of 2
..$ type : chr "B"
..$ score:List of 2
.. ..$ c1: num 9
.. ..$ c2: num 7

R kohonen - Is the input data scaled and centred automatically?

I have been following an online example for R Kohonen self-organising maps (SOM) which suggested that the data should be centred and scaled before computing the SOM.
However, I've noticed the object created seems to have attributes for centre and scale, in which case am I really applying a redundant step by centring and scaling first? Example script below
# Load package
require(kohonen)
# Set data
data(iris)
# Scale and centre
dt <- scale(iris[, 1:4],center=TRUE)
# Prepare SOM
set.seed(590507)
som1 <- som(dt,
somgrid(6,6, "hexagonal"),
rlen=500,
keep.data=TRUE)
str(som1)
The output from the last line of the script is:
List of 13
$ data :List of 1
..$ : num [1:150, 1:4] -0.898 -1.139 -1.381 -1.501 -1.018 ...
.. ..- attr(*, "dimnames")=List of 2
.. .. ..$ : NULL
.. .. ..$ : chr [1:4] "Sepal.Length" "Sepal.Width" "Petal.Length"
"Petal.Width"
.. ..- attr(*, "scaled:center")= Named num [1:4] 5.84 3.06 3.76 1.2
.. .. ..- attr(*, "names")= chr [1:4] "Sepal.Length" "Sepal.Width"
"Petal.Length" "Petal.Width"
.. ..- attr(*, "scaled:scale")= Named num [1:4] 0.828 0.436 1.765 0.762
.. .. ..- attr(*, "names")= chr [1:4] "Sepal.Length" "Sepal.Width"
"Petal.Length" "Petal.Width"
$ unit.classif : num [1:150] 3 5 5 5 4 2 4 4 6 5 ...
$ distances : num [1:150] 0.0426 0.0663 0.0768 0.0744 0.1346 ...
$ grid :List of 6
..$ pts : num [1:36, 1:2] 1.5 2.5 3.5 4.5 5.5 6.5 1 2 3 4 ...
.. ..- attr(*, "dimnames")=List of 2
.. .. ..$ : NULL
.. .. ..$ : chr [1:2] "x" "y"
..$ xdim : num 6
..$ ydim : num 6
..$ topo : chr "hexagonal"
..$ neighbourhood.fct: Factor w/ 2 levels "bubble","gaussian": 1
..$ toroidal : logi FALSE
..- attr(*, "class")= chr "somgrid"
$ codes :List of 1
..$ : num [1:36, 1:4] -0.376 -0.683 -0.734 -1.158 -1.231 ...
.. ..- attr(*, "dimnames")=List of 2
.. .. ..$ : chr [1:36] "V1" "V2" "V3" "V4" ...
.. .. ..$ : chr [1:4] "Sepal.Length" "Sepal.Width" "Petal.Length"
"Petal.Width"
$ changes : num [1:500, 1] 0.0445 0.0413 0.0347 0.0373 0.0337 ...
$ alpha : num [1:2] 0.05 0.01
$ radius : Named num [1:2] 3.61 0
..- attr(*, "names")= chr [1:2] "66.66667%" ""
$ user.weights : num 1
$ distance.weights: num 1
$ whatmap : int 1
$ maxNA.fraction : int 0
$ dist.fcts : chr "sumofsquares"
- attr(*, "class")= chr "kohonen"
Note notice that in lines 7 and 10 of the output there are references to centre and scale. I would appreciate an explanation as to the process here.
Your step with scaling is not redundant because in source code there are no scaling, and attributes, that you see in 7 and 10 are attributes from train dataset.
To check this, just run and compare results of this chunk of code:
# Load package
require(kohonen)
# Set data
data(iris)
# Scale and centre
dt <- scale(iris[, 1:4],center=TRUE)
#compare train datasets
str(dt)
str(as.matrix(iris[, 1:4]))
# Prepare SOM
set.seed(590507)
som1 <- kohonen::som(dt,
kohonen::somgrid(6,6, "hexagonal"),
rlen=500,
keep.data=TRUE)
#without scaling
som2 <- kohonen::som(as.matrix(iris[, 1:4]),
kohonen::somgrid(6,6, "hexagonal"),
rlen=500,
keep.data=TRUE)
#compare results of som function
str(som1)
str(som2)

Control the structure of a nested list when apply FUN returns list or NA

I have a vector v and matrix m and use apply to extract a subset of results from cor.test function (correlations between v and m columns).
set.seed(1)
m <- matrix(runif(12), nrow = 3)
v <- 3:1
res <- apply(m, 2, function(x) {
cor.test(x, v, method = 'spearman', exact = F)[c(1,3,4)]
})
This is a nested list of list with length equal to the number of columns in m - and in the structure I would like as output (2-level list).
> str(res)
List of 4
$ :List of 3
..$ statistic: Named num 8
.. ..- attr(*, "names")= chr "S"
..$ p.value : num 0
..$ estimate : Named num -1
.. ..- attr(*, "names")= chr "rho"
$ :List of 3
..$ statistic: Named num 2
.. ..- attr(*, "names")= chr "S"
..$ p.value : num 0.667
..$ estimate : Named num 0.5
.. ..- attr(*, "names")= chr "rho"
$ :List of 3
..$ statistic: Named num 0
.. ..- attr(*, "names")= chr "S"
..$ p.value : num 0
..$ estimate : Named num 1
.. ..- attr(*, "names")= chr "rho"
$ :List of 3
..$ statistic: Named num 6
.. ..- attr(*, "names")= chr "S"
..$ p.value : num 0.667
..$ estimate : Named num -0.5
.. ..- attr(*, "names")= chr "rho"
I want to filter each cor.test result, say the p.value, within the apply loop and return NA to indicate filtered results (retaining the length of the result, here four).
res <- apply(m, 2, function(x) {
tmp <- cor.test(x, v, method = 'spearman', exact = F)[c(1,3,4)]
ifelse(tmp$p.value < 0.1, list(tmp), NA)
})
My problem is that we now get a 3-level list structure
res2 <- apply(m, 2, function(x) {
tmp <- cor.test(x, v, method = 'spearman', exact = F)[c(1,3,4)]
ifelse(tmp$p.value < 0.1, list(tmp), NA)
})
> str(res2)
List of 4
$ :List of 1
..$ :List of 3
.. ..$ statistic: Named num 8
.. .. ..- attr(*, "names")= chr "S"
.. ..$ p.value : num 0
.. ..$ estimate : Named num -1
.. .. ..- attr(*, "names")= chr "rho"
$ : logi NA
$ :List of 1
..$ :List of 3
.. ..$ statistic: Named num 0
.. .. ..- attr(*, "names")= chr "S"
.. ..$ p.value : num 0
.. ..$ estimate : Named num 1
.. .. ..- attr(*, "names")= chr "rho"
$ : logi NA
Only if the first result from apply is NA the result structure is like desired, obviously since apply then can fit unfiltered result to the structure.
res3 <- apply(m, 2, function(x) {
tmp <- cor.test(x, v, method = 'spearman', exact = F)[c(1,3,4)]
ifelse(tmp$p.value > 0.1, list(tmp), NA) #'invert' the test
})
>res3
List of 4
$ : logi NA
$ :List of 3
..$ statistic: Named num 2
.. ..- attr(*, "names")= chr "S"
..$ p.value : num 0.667
..$ estimate : Named num 0.5
.. ..- attr(*, "names")= chr "rho"
$ : logi NA
$ :List of 3
..$ statistic: Named num 6
.. ..- attr(*, "names")= chr "S"
..$ p.value : num 0.667
..$ estimate : Named num -0.5
.. ..- attr(*, "names")= chr "rho"
I have tried to return ifelse(tmp$p.value < 0.1, tmp, NA) and ifelse(tmp$p.value < 0.1, list(tmp), list(NA)) in vain.
The only solution I found is to assign NA outside the apply:
res4 <- apply(m, 2, function(x) {
cor.test(x, v, method = 'spearman', exact = F)[c(1,3,4)]
})
res4[sapply(res4, "[[", 2) > 0.1] <- NA
Clearly, I miss something about the inner workings of apply.
Your issue isn't with apply but with ifelse. If you use if () {} else {} instead, it works the way you intend
res3 <- apply(m, 2, function(x) {
tmp <- cor.test(x, v, method = 'spearman', exact = F)[c(1,3,4)]
if (tmp$p.value < 0.1) { return(tmp) } else { return(NA) }
})
str(res3)
# List of 4
# $ :List of 3
# ..$ statistic: Named num 8
# .. ..- attr(*, "names")= chr "S"
# ..$ p.value : num 0
# ..$ estimate : Named num -1
# .. ..- attr(*, "names")= chr "rho"
# $ : logi NA
# $ :List of 3
# ..$ statistic: Named num 0
# .. ..- attr(*, "names")= chr "S"
# ..$ p.value : num 0
# ..$ estimate : Named num 1
# .. ..- attr(*, "names")= chr "rho"
# $ : logi NA
Note documentation from ifelse
ifelse returns a value with the same shape as test

Extract statistics from Anderson-Darling test (list)

I would like to extract the p-values from the Anderson-Darling test (ad.test from package kSamples). The test result is a list of 12 containing a 2x3 matrix. The p value is part of the 2x3 matrix and is present in element 7.
When using the following code:
lapply(AD_result, "[[", 7)
I get the following subset of AD test results (first 2 of a total of 50 shown)
[[1]]
AD T.AD asympt. P-value
version 1: 1.72 0.94536 0.13169
version 2: 1.51 0.66740 0.17461
[[2]]
AD T.AD asympt. P-value
version 1: 12.299 14.624 6.9248e-07
version 2: 11.900 14.144 1.1146e-06
My question is how to extract only the p-value (e.g. from version 1) and put these 50 results into a vector
The output from str(AD_result) is:
List of 55
$ :List of 12
..$ test.name : chr "Anderson-Darling"
..$ k : int 2
..$ ns : int [1:2] 103 2905
..$ N : int 3008
..$ n.ties : int 2873
..$ sig : num 0.762
..$ ad : num [1:2, 1:3] 1.72 1.51 0.945 0.667 0.132 ...
.. ..- attr(*, "dimnames")=List of 2
.. .. ..$ : chr [1:2] "version 1:" "version 2:"
.. .. ..$ : chr [1:3] "AD" "T.AD" " asympt. P-value"
..$ warning : logi FALSE
..$ null.dist1: NULL
..$ null.dist2: NULL
..$ method : chr "asymptotic"
..$ Nsim : num 1
..- attr(*, "class")= chr "kSamples"
You could try:
unlist(lapply(AD_result, function(x) x$ad[,3]))

Resources