Applying a Function to Two Lists

Applying a function to two lists?

You seem to be looking for mapply. Here's an example:

listA <- list(matrix(rnorm(2000), nrow=10),
matrix(rnorm(2000), nrow=10))
listB <- list(matrix(rnorm(2000), nrow=10),
matrix(rnorm(2000), nrow=10))
mapply(function(X,Y) {
sapply(1:10, function(row) cor(X[row,], Y[row,]))
}, X=listA, Y=listB)

How applying a function to multiple lists and get a list as the output in R?

As RonakShah said in the comment, Map is likely the answer here.

Think of it this way: lapply applies a function to each element of one list:

myfunc <- function(x) {
# do something with x
}
lapply(1:4, myfunc)
## unrolls to be the equivalent of ...
list(
myfunc(1),
myfunc(2),
myfunc(3),
myfunc(4)
)

Map, however, "zips" each nth element of multiple lists together. The equivalent of the above lapply using Map is

Map(myfunc, 1:4)

but there is a lot more.

myfunc_many <- function(x, y, z) {
# do something with all three args
}
Map(myfunc_many, 1:4, 11:14, 21:24)
## unrolls to
list(
myfunc_many(1, 11, 21),
myfunc_many(2, 12, 22),
myfunc_many(3, 13, 23),
myfunc_many(4, 14, 24)
)

Map can deal with an arbitrary number of lists; if your function is variadic (accepts arbitrary number of arguments), it will still work (though your function has to have built-in mechanisms for dealing with that, making it variadic):

myfunc_variadic <- function(...) {
dots <- list(...)
# do something with dots
}
Map(myfunc_variadic, 1:4)
Map(myfunc_variadic, 1:4, 11:14)
Map(myfunc_variadic, 1:4, 11:14, 21:24, 31:34, 41:44)

In all of the examples above, I've used vectors as each argument, but it works just as well with lists of things. As a final example,

set.seed(42)
L1 <- replicate(2, matrix(sample(6), nrow = 2), simplify = FALSE)
L2 <- replicate(2, matrix(sample(6), nrow = 2), simplify = FALSE)
L1
# [[1]]
# [,1] [,2] [,3]
# [1,] 1 6 2
# [2,] 5 4 3
# [[2]]
# [,1] [,2] [,3]
# [1,] 2 1 5
# [2,] 6 3 4
L2
# [[1]]
# [,1] [,2] [,3]
# [1,] 4 5 3
# [2,] 1 2 6
# [[2]]
# [,1] [,2] [,3]
# [1,] 2 1 5
# [2,] 3 4 6
Map(`*`, L1, L2)
# [[1]]
# [,1] [,2] [,3]
# [1,] 4 30 6
# [2,] 5 8 18
# [[2]]
# [,1] [,2] [,3]
# [1,] 4 1 25
# [2,] 18 12 24

How to apply a function on two lists of data frames?

We can use Map to apply the function on corresponding elements of 'list_A' and 'list_B'

Map(`*`, list_A, list_B)

As @RHertel mentioned in the comments, if the function needed is %*%

 Map(function(x,y) as.matrix(x) %*% as.matrix(y), list_A, list_B)

How to apply the same function to multiple lists

I'm not sure whether I understood your question correctly. As fgblomqvist commented, I replaced 1 if 'a' in a by 1 if x == 'a' in the list comprehension. Then I basically reproduced your second step with a for-loop and after that I used zip to iterate over the list values of all lists synchronously in order to calculate the sum.

a = ['a','b','c','d','e']
b = ['b','a','c','e','a']
c = ['a','b','c','d','e']

# add the lists to a list.
lists = [a,b,c]

outcomes = []
for l in lists:
outcome = [1 if x == 'a' else 99 for x in l]
outcomes.append(outcome)
print(f'one of the outcomes: {outcome}')

results = []

# iterate over all list values synchronously and calculate the sum
for outs in zip(*outcomes):
results.append(sum(outs))
print(f'sum of {outs} is {sum(outs)}')

print(f'final result:{results}')

This is the output:

one of the outcomes: [1, 99, 99, 99, 99]
one of the outcomes: [99, 1, 99, 99, 1]
one of the outcomes: [1, 99, 99, 99, 99]
sum of (1, 99, 1) is 101
sum of (99, 1, 99) is 199
sum of (99, 99, 99) is 297
sum of (99, 99, 99) is 297
sum of (99, 1, 99) is 199
final result:[101, 199, 297, 297, 199]

edit: To avoid looping twice you could join the loops together like so:

lists = [a,b,c]

sums = []
for values in zip(*lists):
the_sum = 0
for val in values:
the_sum += 1 if val == 'a' else 99
sums.append(the_sum)

print(f'sums: {sums}')

Keep in mind you can replace the 1 if val == 'a' else 99 by some_func(val)

Lapplying a function over two lists of dataframes in R

Here, we could use Map from base R to apply the function on the corresponding elements of both the lists

out <- Map(my_function, list_A, list_B)

lapply can also be used, if we loop over the sequence of one of the list

out <- lapply(seq_along(list_A), function(i) 
my_function(list_A[[i]], list_B[[i]]))

which is similar to using a for loop

out <- vector('list', length(list_A))
for(i in seq_along(list_A)) out[[i]] <- my_function(list_A[[i]], list_B[[i]])

Apply a function to each combination of two lists elements

Or another option with pmap and crossing

library(tidyr)
library(purrr)
library(dplyr)
crossing(v1 = 0:1, v2 = 1:2) %>%
pmap_dbl(~ qnorm(p = 0.05, mean = ..1, sd = ..2, lower.tail = FALSE))
[1] 1.644854 3.289707 2.644854 4.289707

If we need a data.frame/tibble, use the pmap code within the mutate to return as a new column

crossing(v1 = 0:1, v2 = 1:2) %>%
mutate(new = pmap_dbl(., ~ qnorm(p = 0.05,
mean = ..1, sd = ..2, lower.tail = FALSE)))
# A tibble: 4 × 3
v1 v2 new
<int> <int> <dbl>
1 0 1 1.64
2 0 2 3.29
3 1 1 2.64
4 1 2 4.29

NOTE: If we don't need the other columns, use transmute instead of mutate or specify .keep = "used" in mutate

crossing(v1 = 0:1, v2 = 1:2) %>%
mutate(new = pmap_dbl(., ~ qnorm(p = 0.05,
mean = ..1, sd = ..2, lower.tail = FALSE)), .keep = "used")
# A tibble: 4 × 1
new
<dbl>
1 1.64
2 3.29
3 2.64
4 4.29

Run a function for each element in two lists in Pandas Dataframe Columns

This works:

# Generate DataFrame
df = pd.DataFrame (data, columns = ['col1','col2'])

# Clean Data (strip out trailing commas on some words)
df['col1'] = df['col1'].map(lambda lst: [x.rstrip(',') for x in lst])

# 1. List comprehension Technique
# zip provides pairs of col1, col2 rows
result = [[get_top_matches(u, [v]) for u in x for w in y for v in w] for x, y in zip(df['col1'], df['col2'])]

# 2. DataFrame Apply Technique
def func(x, y):
return [get_top_matches(u, [v]) for u in x for w in y for v in w]

df['func_scores'] = df.apply(lambda row: func(row['col1'], row['col2']), axis = 1)

# Verify two methods are equal
print(df['func_scores'].equals(pd.Series(result))) # True

print(df['func_scores'].to_string(index=False))

Thanks all who helped

applying a function to multiple lists (R)

For the example shared, where all the elements of source have the same order you can do :

cols <- paste0('source.val_', sort(unique(unlist(source))))
setNames(do.call(rbind.data.frame, source.val), cols)

# source.val_5 source.val_10 source.val_20 source.val_30
#1 A B C D
#2 B B D D
#3 C B A D
#4 D B B D

However, for a general case where every value in source do not follow the same order you can reorder source.val based on source :

source.val <- Map(function(x, y) y[order(x)], source, source.val)

and then use the above code.

How to apply a function to two elements of a list - Haskell

yes on way is to define a recursive function - what you need to think about (and what we don't know) is what should happen if the input list has uneven item-count?
And of course how do you want to collect the results of that function?

Assuming you just ignore the last singe element in an uneven list and that you want to collect the results into another list:

applyPairwise :: (a -> a -> b) -> [a] -> [b]
applyPairwise f (a1 : a2 : rest) = f a1 a2 : applyPairwise f rest
applyPairwise _ _ = []

Example:

> applyPairwise (+) [1..5]
[3,7]


Related Topics



Leave a reply



Submit