Amberopolis
Amberopolis

Reputation: 455

indexing through values of a nested list using mapply

I have a list of lists, with each sub-list containing 3 values. My goal is to cycle through every value of this nested list in a systematic way (i.e. start with list 1, go through all 3 values, go to list 2, and so on), applying a function to each. But my function hits missing values and breaks and I've traced the problem to the indexing itself, which doesn't behave in the way I am expecting. The lists are constructed as:

pop <- 1:100
treat.temp <- NULL
treat <- NULL

## Generate 5 samples of pop
for (i in 1:5){
    treat.temp <- sample(pop, 3)
    treat[[i]] <- treat.temp
}

## Create a list with which to index mapply
iterations <- (1:5)

Illustrative function and results.

test.function <- function(j, k){
  for (n in 1:3){
    print(k[[n]][j])
  }
}

results <- mapply(test.function, iterations, treat)

[1] 61
[1] 63
[1] 73
[1] NA
[1] NA
[1] NA
[1] NA
[1] NA
<snipped>

For the first cycle through 'j', this works. But after that it throws NAs. But if I do it manually, it returns the values I would expect.

> print(treat[[1]][1])
[1] 61
> print(treat[[1]][2])
[1] 63
> print(treat[[1]][3])
[1] 73
> print(treat[[2]][1])
[1] 59
> print(treat[[2]][2])
[1] 6
> print(treat[[2]][3])
[1] 75
<snipped>

I'm sure this is a basic question, but I can't seem to find the right search terms to find an answer here or on Google. Thanks in advance!

Edited to Add: MrFlick's answer works well for my problem. I have multiple list inputs (hence mapply) in my actual use. A more detailed example, with a few notes.

pop <- 1:100
years <- seq.int(2000, 2014, 1)

treat.temp <- NULL
treat <- NULL
year.temp <- NULL
year <- NULL

## Generate 5 samples of treated states, control states and treatment years 
for (i in 1:5){
  treat.temp <- sample(pop, 20)
  treat[[i]] <- treat.temp

  year.temp <- sample(years, 1)
  year[[i]] <- year.temp
}

## Create a list with which to index mapply
iterations <- (1:5)

## Define function 
test.function <- function(j, k, l){
  for (n in 1:3){

    ## Cycles treat through each value of jXn
    print(k[n])
    ## Holds treat (k) fixed for each 3 cycle set of n (using first value in each treat sub-list); cycles through sub-lists as j changes
    print(k[1])
    ## Same as above, but with 2nd value in each sub-list of treat
    print(k[2])
    ## Holds year (l) fixed for each 3 cycle set of n, cycling through values of year each time j changes
    print(l[1])
    ## Functionally equivalent to
    print(l)
  }
}

results <- mapply(test.function, iterations, treat, year)

Upvotes: 1

Views: 395

Answers (1)

MrFlick
MrFlick

Reputation: 206243

Well, you might be misunderstanding how mapply works. The function will loop through both of the iterations you pass as parameters, which means treat will also be subset each iteration. Essentially, the functions being called are

test.function(iterations[1], treat[[1]])
test.function(iterations[2], treat[[2]])
test.function(iterations[3], treat[[3]])
...

and you seem to treat the k variable as if it were the entire list. Also, you have your indexes backwards as well. But just to get your test working, you can do

test.function <- function(j, k){
  for (n in 1:3) print(k[n]) 
}

results <- mapply(test.function, iterations, treat)

but this isn't really a super awesome way to iterate a list. What exactly are you trying to accomplish?

Upvotes: 2

Related Questions