Solebay Sharp
Solebay Sharp

Reputation: 533

How to create a list inside a list, using elements from one vector, in r

I am trying to create lists inside lists using a single vector in R.

I have the vector

Conditions = c('A', 'B', 'C', 'D')

and I want a list containing A, B, C and D (no problem). But then I also want those to be lists containing four items named along the lines of: A vs A, A vs B, ... D vs C, D vs D, ultimately ending up with a list of four lists (A, B, C, and D) each containing four further lists ('vs' lists) that I can add data frames to.

essentially I want something like this:

My list
 |
 |
 |        /- A vs A       /- B vs A      /- C vs A      /- D vs A
 |       /               /              /              /
 |      /- A vs B       /- B vs B      /- C vs B      /- D vs B
 |     /               /              /              /
 ---A-|-------------B-|------------C-|------------D-|                       
       \               \              \              \
        \ - A vs C      \ - B vs C     \ - C vs C     \ - D vs C
         \               \              \              \  
          \- A vs D       \- B vs D      \- C vs D      \- D vs D

This is what I have tried:

Conditions <- c('A', 'B', 'C', 'D')

MyList <- as.list(Conditions) 

for(i in 1:length(MyList)) {
    for(i in 1:length(Conditions)) {
    MyList[i] <- list(paste(MyList[i], 'vs', Conditions[i]))
  }
}

But it doesn't work. For instance my first item just gets turned from A to A vs A vs A vs A vs A.

Edit: for greater clarification I would like,

A list e.g.,

Letters

That will contain four lists,

A , B , C, D

These in turn will contain lists, corresponding to their names:

A: A vs A, A vs B, A vs C, A vs D B: B vs A, B vs B, B vs C, B vs D C: C vs A, C vs B, C vs C, C vs D D: D vs A, D vs B, D vs C, D vs D

I will then put a data frame into each 'vs'.

The most helpful answer so far was from MrFlick:

lapply(Conditions, function(x) 
  as.list(paste(x, "vs", Conditions)))

Which returns:

[[1]]
[[1]][[1]]
[1] "A vs A"

[[1]][[2]]
[1] "A vs B"

[[1]][[3]]
[1] "A vs C"

...

[[4]][[2]]
[1] "D vs B"

[[4]][[3]]
[1] "D vs C"

[[4]][[4]]
[1] "D vs D"

All I want is for the list to be empty, and the string to be used as a name. For the element just above I think it would look like this:

[[D]][[D vs D]]
    [1] NA        #Data Frame DvsD.Rda to be added here later.

Upvotes: 1

Views: 1051

Answers (4)

Jet
Jet

Reputation: 690

I think what you are trying to do is someting like this :

Conditions <- c('A', 'B', 'C', 'D')

MyList = lapply(Conditions, function(x) list())
names(MyList) = Conditions

for(i in names(MyList)) {
    for(j in 1:length(Conditions)) {
        MyList[[i]][[paste(i, 'vs', Conditions[j])]] = NA #Put NA or the data frame you want.
    }
}

Output :

$A
$A$`A vs A`
[1] NA

$A$`A vs B`
[1] NA

$A$`A vs C`
[1] NA

$A$`A vs D`
[1] NA


$B
$B$`B vs A`
[1] NA

$B$`B vs B`
[1] NA

$B$`B vs C`
[1] NA

$B$`B vs D`
[1] NA


$C
$C$`C vs A`
[1] NA

$C$`C vs B`
[1] NA

$C$`C vs C`
[1] NA

$C$`C vs D`
[1] NA


$D
$D$`D vs A`
[1] NA

$D$`D vs B`
[1] NA

$D$`D vs C`
[1] NA

$D$`D vs D`
[1] NA

Upvotes: 3

boski
boski

Reputation: 2467

If your logic is always the same, try

Conditions = c('A', 'B', 'C', 'D')
L=setNames(as.list(Conditions),Conditions)

L=lapply(L, function(x){
  setNames(vector("list",length(Conditions)),paste0(x," vs ",Conditions))
})

> str(L)
List of 4
 $ A:List of 4
  ..$ A vs A: NULL
  ..$ A vs B: NULL
  ..$ A vs C: NULL
  ..$ A vs D: NULL
 $ B:List of 4
  ..$ B vs A: NULL
  ..$ B vs B: NULL
  ..$ B vs C: NULL
  ..$ B vs D: NULL
 $ C:List of 4
  ..$ C vs A: NULL
  ..$ C vs B: NULL
  ..$ C vs C: NULL
  ..$ C vs D: NULL
 $ D:List of 4
  ..$ D vs A: NULL
  ..$ D vs B: NULL
  ..$ D vs C: NULL
  ..$ D vs D: NULL

Upvotes: 1

MrFlick
MrFlick

Reputation: 206197

It sounds like you want

lapply(Conditions, paste, "vs", Conditions)

That's assuming vectors are OK in the list. If you need lists, then you can do

lapply(Conditions, function(x) as.list(paste(x, "vs", Conditions)))

If you need to give the main list names, use setNames()

Upvotes: 1

TheRimalaya
TheRimalaya

Reputation: 4592

Here is my solution, have a look,

vec <- c("A", "B", "C", "D")

res <- lapply(vec, function(x) {
    out <- expand.grid(x, vec)
    lapply(1:nrow(out), function(y) {
        paste(out[y, 1], " vs ", out[y, 2])
    })
})
str(res)

Result:

List of 4
 $ :List of 4
  ..$ : chr "A  vs  A"
  ..$ : chr "A  vs  B"
  ..$ : chr "A  vs  C"
  ..$ : chr "A  vs  D"
 $ :List of 4
  ..$ : chr "B  vs  A"
  ..$ : chr "B  vs  B"
  ..$ : chr "B  vs  C"
  ..$ : chr "B  vs  D"
 $ :List of 4
  ..$ : chr "C  vs  A"
  ..$ : chr "C  vs  B"
  ..$ : chr "C  vs  C"
  ..$ : chr "C  vs  D"
 $ :List of 4
  ..$ : chr "D  vs  A"
  ..$ : chr "D  vs  B"
  ..$ : chr "D  vs  C"
  ..$ : chr "D  vs  D"

Upvotes: 1

Related Questions