Multiplying Combinations of a list of lists in R
Have no idea if this is fast or memory intensive just that it works, Joris Meys's answer is more eloquent:
x <- expand.grid(1:length(a), 1:length(b))
x <- x[order(x$Var1), ] #gives the order you asked for
FUN <- function(i) diag(outer(a[[x[i, 1]]], b[[x[i, 2]]], "*"))
sapply(1:nrow(x), FUN) #I like this out put
lapply(1:nrow(x), FUN) #This one matches what you asked for
EDIT: Now that Brian introduced benchmarking (which I love (LINK)) I have to respond. I actually have a faster answer using what I call expand.grid2 that's a lighter weight version of the original that I stole from HERE. I was going to throw it up before but when I saw how fast Joris's is I figured why bother, both short and sweet but also fast. But now that Diggs has dug I figured I'd throw up here the expand.grid2
for educational purposes.
expand.grid2 <-function(seq1,seq2) {
cbind(Var1 = rep.int(seq1, length(seq2)),
Var2 = rep.int(seq2, rep.int(length(seq1),length(seq2))))
}
x <- expand.grid2(1:length(a), 1:length(b))
x <- x[order(x[,'Var1']), ] #gives the order you asked for
FUN <- function(i) diag(outer(a[[x[i, 1]]], b[[x[i, 2]]], "*"))
lapply(1:nrow(x), FUN)
Here's the results (same labeling as Bryan's except TylerEG2 is using the expand.grid2
):
Unit: microseconds
expr min lq median uq max
1 DiggsL(a, b) 5102.296 5307.816 5471.578 5887.516 70965.58
2 DiggsM(a, b) 384.912 428.769 443.466 461.428 36213.89
3 Joris(a, b) 91.446 105.210 123.172 130.171 16833.47
4 TylerEG2(a, b) 392.377 425.503 438.100 453.263 32208.94
5 TylerL(a, b) 1752.398 1808.852 1847.577 1975.880 49214.10
6 TylerM(a, b) 1827.515 1888.867 1925.959 2090.421 75766.01
7 Wojciech(a, b) 1719.740 1771.760 1807.686 1924.325 81666.12
And if I take the ordering step out I can squeak out even more but it still isn't close to Joris's answer.
Multiplying two different lists objects in R
You can use map
as shown below:
Map('*',x,y)
Output of the above code is shown below:
> Map('*',x,y)
[[1]]
[,1] [,2]
[1,] 1 0
[2,] 0 4
[[2]]
[,1] [,2]
[1,] 0 0
[2,] 6 8
OR
You can use unlist
to unlist list and multiple list together:
Listxy <- list(unlist(x)*unlist(y))
Listxy
[[1]]
[1] 1 0 0 4 0 6 0 8
How to multiply a list of vector by list of arrays (by columns) in R
We can try with Map
res <- Map(function(u, v) {
u[u!=0] <- u[u!=0]*rep(v, dim(u)[3])
u},
a, x)
a[[1]][2,1,1]*x[[1]][1]
#[1] 0.3840722
a[[1]][2,1,2]*x[[1]][1]
#[1] -0.8685313
res[[1]][2, 1, 1]
#[1] 0.3840722
res[[1]][2, 1, 2]
#[1] -0.8685313
Matrix calculation between list objects in R
We can use combn
to create pairwise combination on the sequence of the list
, extract the elements and do the multiplication
new_lst <- combn(seq_along(results), 2, \(i) matr[,i[1]] * matr[,i[2]] *
results[[i[1]]] * results[[i[2]]], simplify = FALSE)
names(new_lst) <- combn(seq_along(results), 2, paste, collapse="_")
-output
> new_lst
$`1_2`
[,1] [,2] [,3]
[1,] 64.135122 2.6966755 12.4307531
[2,] 2.696676 0.1133865 0.5226732
[3,] 12.430753 0.5226732 2.4093448
$`1_3`
[,1] [,2] [,3]
[1,] 5.775451 -1.2624981 -5.095849
[2,] -1.262498 0.2759787 1.113939
[3,] -5.095849 1.1139391 4.496217
$`1_4`
[,1] [,2] [,3]
[1,] 18.46710 -2.275650 -18.610758
[2,] -2.27565 0.280422 2.293352
[3,] -18.61076 2.293352 18.755530
$`2_3`
[,1] [,2] [,3]
[1,] 43.621251 -7.589849 -9.242303
[2,] -7.589849 1.320590 1.608108
[3,] -9.242303 1.608108 1.958223
$`2_4`
[,1] [,2] [,3]
[1,] 139.47970 -13.680683 -33.754187
[2,] -13.68068 1.341852 3.310735
[3,] -33.75419 3.310735 8.168537
$`3_4`
[,1] [,2] [,3]
[1,] 12.560327 6.404863 13.837154
[2,] 6.404863 3.266019 7.055953
[3,] 13.837154 7.055953 15.243778
multiply two lists of irregular length
We may indeed use mapply
(and Map
, which is the same as mapply
but with SIMPLIFY = FALSE
). Depending on the format (matrix as in @RonakShah's answer or a list as in your question), you may use
Map(mapply, a, b, MoreArgs = list(FUN = `*`))
# [[1]]
# [,1] [,2] [,3]
# [1,] -14 32 18
# [2,] 7 40 27
#
# [[2]]
# [,1] [,2]
# [1,] 0 1
# [2,] 10 -1
or
Map(Map, a, b, MoreArgs = list(f = `*`))
# [[1]]
# [[1]][[1]]
# [1] -14 7
#
# [[1]][[2]]
# [1] 32 40
#
# [[1]][[3]]
# [1] 18 27
#
#
#[[2]]
# [[2]][[1]]
# [1] 0 10
#
# [[2]][[2]]
# [1] 1 -1
A tidyverse
alternative to the latter is
map2(a, b, map2, `*`)
Prolog - finding all combinations (The product) of List of Lists (of Lists)
I'm not so sure this is the most efficient approach, but it's fairly transparent. The idea here is to define the problem in recursive (or inductive) "layers":
% multiply_lists(ListOfLists, MultipliedListOfLists)
%
% The first two clauses handle the case where ListOfLists consists
% of just one list
% The third clause handles the general case
%
multiply_lists([[X]], [[X]]).
multiply_lists([[X|Xs]], [[X]|T]) :-
multiply_lists([Xs], T).
multiply_lists([E|Es], R) :-
multiply_lists(Es, R1),
multiply_list(E, R1, R).
% multiply_list relates the product of a list of lists and a single list
% of elements
%
multiply_list([], _, []).
multiply_list([E|Es], L, Ls) :-
multiply_list(Es, L, LL),
multiply_element(E, L, LL, Ls).
% multiply_element relates the product, prepended to a given list,
% of a single list of lists and a single element
%
multiply_element(_, [], A, A).
multiply_element(X, [Y|Ys], A, [[X|Y]|T]) :-
multiply_element(X, Ys, A, T).
multiply_element/4
actually combines two rules into one: it defines multiplication of a list by a single element, and prepends those results as individual elements to a given list.
A sample result:
| ?- multiply_lists([[1, 2], [1, 2, 3]], L).
L = [[1,1],[1,2],[1,3],[2,1],[2,2],[2,3]] ? ;
no
| ?- multiply_lists([[a,b,c], [1,2], [x,y]], L).
L = [[a,1,x],[a,1,y],[a,2,x],[a,2,y],[b,1,x],[b,1,y],[b,2,x],[b,2,y],[c,1,x],[c,1,y],[c,2,x],[c,2,y]] ? ;
no
Some quirks with the above implementation:
- It's not tail recursive (so will use more stack as the lists get longer)
- It leaves a choice point
But it does illustrate how the problem can be solved without using append/3
or other list-based pre-defined predicates.
Related Topics
Error: Package or Namespace Load Failed for 'Car'
Adding a Legend to an Rgl 3D Plot
Error with H2O in R - Can't Connect to Local Host
Classic Case of 'Sum' Returning Na Because It Doesn't Sum Nas
How to Split a Vector by Delimiter
Multiplying Vector Combinations
How to Custom or Display Modebar in Plotly
R:Function to Generate a Mixture Distribution
Ggplot Scale_X_Continuous with Symbol: Make Bold
Place Text Values to Right of Sankey Diagram
Ggplot: How to Produce a Gradient Fill Within a Geom_Polygon
How to Pop Up the Graphics Window from Rscript
Placement of Error Bars in Barplot Using Ggplot2
Plotly - Different Colours for Different Surfaces
R: Reading a Binary File That Is Zipped
Assignment to Empty Index (Empty Square Brackets X[]<-) on Lhs
Preventing Incosistent Spacing/Bar Widths in Geom_Bar with Many Bars