Create a list from matrix in R - r

I have two lists v and w and I would like to create again a list z from matrix M . How can I do this in R?
v = list(a = c(1, 5), b = 2, c= 3)
w = list( a= c(2, 10), b = 4, c = 6)
M = as.matrix(unlist( v) * unlist(w))
> M
[,1]
a1 2
a2 50
b 8
c 18
z = list(a = c(2, 50), b = 8, c = 18)

Do it like this:
mapply(`*`, v, w)

Maybe you want z <- lapply(1:length(v), function(i) v[[i]]*w[[i]])? Add names(z) <- names(v) to keep the names.

Related

Unlist LAST level of a list in R

I have a list of list like ll:
ll <- list(a = list(data.frame(c = 1, d = 2), data.frame(h = 3, j = 4)), b = list(data.frame(c = 5, d = 6), data.frame(h = 7, j = 9)))
I want to unnest/unlist the last level of the structure (the interior list). Note that every list contains the same structure. I want to obtain lj:
lj <- list(a = (data.frame(c = 1, d = 2, h = 3, j = 4)), b = data.frame(c = 5, d = 6, h = 7, j = 9))
I have tried the following code without any success:
lj_not_success <- unlist(ll, recursive = F)
However, this code unlists the FIRST level, not the LAST one.
Any clue?
We may need to cbind the inner list elements instead of unlisting as the expected output is a also a list of data.frames
ll_new <- lapply(ll, function(x) do.call(cbind, x))
-checking
> identical(lj, ll_new)
[1] TRUE

Unpack a list by duplicating elements longer than 1

I have the following list that I wish to unpack (aka expand) using only base R.
For example, I want to turn this:
b <- list(a = c(1, 2), b = 1, d = c(5, 7))
into the equivalent of:
list(a = 1, a = 2, b = 1, d = 5, d = 7)
I have this function that works if only one named element has length > 1 but not if there are multiple elements:
expand_list <- function(listx){
long_elements <- as.numeric(which(lapply(listx, length) > 1))
short_elements <- as.numeric(which(lapply(listx, length) == 1))
res <- lapply(long_elements, function(x){
as.list(setNames(listx[[x]], rep(names(listx)[x], length(listx[[x]]))))
})
expanded_elements <- res[[1]]
c(listx[short_elements], expanded_elements)
}
expand_list(b)
You can use stack followed by setNames to achieve that
y <- list(a = c(1, 2), b = 1, c = 2, d = c(5, 7))
x <- stack(y)
as.list(setNames(x$values, x$ind))

Calculation in a loop in R

Consider the following data:
library(Benchmarking)
x <- c(2, 3, 8)
y <- c(1, 5, 10)
k <- 25
d <- data.frame(x,y,k)
x <- c(5, 2, 3, 4)
y <- c(3, 5, 9, 10)
k <- 30
d2 <- data.frame(x,y,k)
d3 <- replicate(3, rbind(d, d2[sample(seq_len(nrow(d2)), 3), , drop=FALSE]), simplify = FALSE)
So now I have a list of 3 data.frame. For each of these 3 data.frame I want to perform the following calculation:
e1 <- with(subset(d3[[1]], k == 25), dea(d3[[1]]$x, d3[[1]]$y, XREF = x, YREF = y))
e2 <- with(subset(d3[[1]], k == 30), dea(d3[[1]]$x, d3[[1]]$y, XREF = x, YREF = y))
we1 <- weighted.mean(eff(e1), d3[[1]]$y)
we2 <- weighted.mean(eff(e2), d3[[1]]$y)
va <- we2/we1
But instead of using that code three times, where I change [[1]] to [[2]] and [[3]], can I instead use a loop, where it does the calculation for all 3 data.frame and create a new data.frame where it list va for the three calculations?
We create a function and then loop through the list and apply the function
f1 <- function(dat) {
d1 <- subset(dat, k == 25)
e1 <- with(d1, dea(dat$x, dat$y, XREF = x, YREF = y))
d2 <- subset(dat, k == 30)
e2 <- with(d2, dea(dat$x, dat$y, XREF = x, YREF = y))
we1 <- weighted.mean(eff(e1), dat$y)
we2 <- weighted.mean(eff(e2), dat$y)
we2/we1
}
sapply(d3, f1)

how to apply functions on data frame in r

How can i apply the following function rt on each and every value l in df.
x and y have the following values.
x<-9
y<-1
rt<-function(x,y,l) min(x,max(0,l-y))
df
a b c
5 6 7
1 4 1
2 4 3
Probably simplest if you'd like to stick with dataframes is to use apply with the MARGIN parameter set to c(1,2), which makes it apply the function by both rows and columns (i.e., to every cell).
x <- 9
y <- 1
rt <- function(x, y, l) min(x, max(0, l-y))
df <- data.frame(a = c(5, 1, 2),
b = c(6, 4, 4),
c = c(7, 1, 3))
rt_df <- as.data.frame(apply(df, c(1,2), rt, x = x, y = y))

Subset list, keep names

I have list out like this:
u <- list(a = list(b = 1, c = 2),
x = list(k = list(ka = 1, kb = 3),
l = list(la = 1, la = 4)))
v <- list(a = list(b = 1, c = 2),
x = list(m = list(ma = 5, mb = 8),
n = list(na = 5, nb = 8)))
w <- list(a = list(b = 1, c = 2),
x = list(o = list(oa = 4, ob = 1),
p = list(pa = 8, pb = 0)))
out <- list(u, v, w)
I would like to create another list where there are elements k, l, m, n, o, p and names of the list elements are preserved. I found a solution, but looks sub-optimal:
x <- lapply(out, function(y) y[['x']])
o <- list()
for (a in x) {
o <- c(o, a)
}
> str(o, max.level = 1)
List of 6
$ k:List of 2
$ l:List of 2
$ m:List of 2
$ n:List of 2
$ o:List of 2
$ p:List of 2
Is there a better way?
The loop could be replaced with unlist:
res <- unlist( lapply(out,"[[","x"), recursive=FALSE)
identical(res,o)
# [1] TRUE
My lapply is the same as in the OP; it's just a shortcut.
As #akrun suggested, you could more closely mirror the OP's loop with
do.call("c", lapply(out, '[[', 'x'))

Resources