1

So here, i get errors with imap, when using the index (".y") to go through a list. below I have made it work with map2, but this is confusing, because the way I made the map2() function is exacly the same way I would've thought that imap would do it. But it clearly isn't, otherwise it wouldn't error out.

I would love to understand the purrr logic as good as possible, could anyone tell me what's going on?

library(purrr)

l1 <- list(a='a', b='b')



# single brackets -  'missing value where TRUE/FALSE needed'
imap(l1, ~{
  y1 <- names(l1)[.y]
  if(y1 == 'a') out1 <- TRUE
  if(y1 == 'b') out1 <- FALSE
  out
})
# double brackets -  subscript out of bounds
imap(l1, ~{
  y1 <- names(l1)[[.y]]
  if(y1 == 'a') out1 <- TRUE
  if(y1 == 'b') out1 <- FALSE
  out
})


# emulating what I think imap() does 
map2(l1, seq_along(l1), ~{
  y1 <- names(l1)[.y]
  if(y1 == 'a') out1 <- TRUE
  if(y1 == 'b') out1 <- FALSE
  out1
})
emilBeBri
  • 625
  • 13
  • 18

2 Answers2

1

If the names are present in the list, .y is the name of the list and not it's index. So,

names(l1)['a'] #returns
#[1] NA

which explains 'missing value where TRUE/FALSE needed'.

and

names(l1)[['a']]

returns

Error in names(l1)[["a"]] : subscript out of bounds

What you need is -

purrr::imap(l1, ~{
  if(.y == 'a') out1 <- TRUE
  if(.y == 'b') out1 <- FALSE
  out1
})

#$a
#[1] TRUE

#$b
#[1] FALSE
Ronak Shah
  • 377,200
  • 20
  • 156
  • 213
1

perhaps you simply need

imap(l1, ~ if(.y == 'a')  TRUE else FALSE)

$a
[1] TRUE

$b
[1] FALSE
AnilGoyal
  • 25,297
  • 4
  • 27
  • 45