This is probably a duplicate, but I don’t seem to find this specific case.
Say I have two lists:
list1 <- as.list(c(5, 8, 9))
list2 <- as.list(c(8, 10, 11))
I know how to apply a function to one list. Say I want to apply the following to list1
:
lapply(list1, function(x){x+100})
But what if I only want to apply such function to list1
when the corresponding value in list2
is >=10
? So that my result is:
[[1]]
[1] 5
[[2]]
[1] 108
[[3]]
[1] 109
And even more, how can I sum 100 to the value in list1
and subtract the value in list2
only when the value in list2
is >=10
?
Something like the following, which obviously does not work:
lapply(list1, list2, function(x,y){if (y>=10) x+100-y})
Thanks!
I think you’re looking for Map()
, which is mapply()
without simplification:
mapply
is a multivariate version ofsapply
.mapply
appliesFUN
to the first elements of each...
argument, the second elements, the third elements, and so on.
For reasons that I imagine are only known to the R devs, unlike lapply()
, sapply()
and tapply()
, the function is the first argument of mapply()
and Map()
.
Map(
(x1, x2) if (x2 >= 10) x1 + 100 else x1,
list1,
list2
)
# [[1]]
# [1] 5
# [[2]]
# [1] 108
# [[3]]
# [1] 109
If you want to be fancy you could remove the if()
statement and define the function as (x1, x2) x1 + 100 * (x2 >= 10)
but personally I think the lack of explicitness makes it less comprehensible.
Of course you could also do this with ifelse(list2 >= 10, unlist(list1) + 100, list1)
in this case but Map()
is more general.
Your second example could be expressed as Map((x, y) if (y >= 10) x + 100 - y else x, list1, list2)
.
Given the toy example, I do not see why we use a list format. Things get easier if we work with vectors instead:
list1 <- as.list(c(5, 8, 9))
list2 <- as.list(c(8, 10, 11))
x1 = unlist(list1)
x2 = unlist(list2)
and then apply a fully vectorised
x1 + 100 * (x2 >= 10)
# [1] 5 108 109
Note. Notation taken from user @SamR’s solution.
4
A variant of using Map
> Map(`+`, list1, 100 * (unlist(list2) >= 10))
[[1]]
[1] 5
[[2]]
[1] 108
[[3]]
[1] 109