1

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)
2
  • Your example set-up is a list of vectors, in which case it seems straightforward to apply some function to every value in each vector using lapply - as in, lapply(treat, function(x) x/2) if you just wanted to divide everything by 2. Could you clarify your problem a bit more? Commented Jun 26, 2014 at 16:04
  • I think you're right (as is MrFlick below) regarding lapply in my example. I've added a more detailed example for posterity. I use mapply because I have multiple input lists and some need to be cycled with j but stay fixed over all iterations of n, while others need to cycle with both j and n. It's possible lapply can handle that, I just don't know how. Commented Jun 26, 2014 at 17:51

1 Answer 1

2

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?

Sign up to request clarification or add additional context in comments.

2 Comments

Can you explain why it's suboptimal to iterate through a list this way?
If you just wanted those values in that order you could just do unlist(treat). There's nothing super wrong with doing it that way, it just seems like it may be easier to an lapply or something on the list itself. It depends on what you are doing with the values I guess.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.