Apply to list of vectors

心不动则不痛 提交于 2019-12-08 06:40:57

问题


I have list of numerical vectors (with different sizes each) in R. Let's say the list has 10 elements.

I would like to apply a function (something like max(x - K, 0) where K is a fixed constant) to each elements of each vector of the list, and get an output with exactly the same structure (thus a list of vectors).

I tried sapply(data, function(x) max(x-K, 0)) but I get a vector of size 10. I don't know exactly what are its components by the way. I also tried max(data-K,0) directly, but I get an error message.

Can anyone help me ?


回答1:


## dummy data
set.seed(1)
ll <- as.list(data.frame(matrix(rnorm(10 * 10), ncol = 10)))

R> str(ll)
List of 10
 $ X1 : num [1:10] -0.626 0.184 -0.836 1.595 0.33 ...
 $ X2 : num [1:10] 1.512 0.39 -0.621 -2.215 1.125 ...
 $ X3 : num [1:10] 0.919 0.7821 0.0746 -1.9894 0.6198 ...
 $ X4 : num [1:10] 1.3587 -0.1028 0.3877 -0.0538 -1.3771 ...
 $ X5 : num [1:10] -0.165 -0.253 0.697 0.557 -0.689 ...
 $ X6 : num [1:10] 0.398 -0.612 0.341 -1.129 1.433 ...
 $ X7 : num [1:10] 2.4016 -0.0392 0.6897 0.028 -0.7433 ...
 $ X8 : num [1:10] 0.476 -0.71 0.611 -0.934 -1.254 ...
 $ X9 : num [1:10] -0.569 -0.135 1.178 -1.524 0.594 ...
 $ X10: num [1:10] -0.543 1.208 1.16 0.7 1.587 ...

With this, what you had is correct if you want an atomic vector output. To see the relationship look at the names of the vector elements

R> ( out <- sapply(ll, function(x, K) max(x - K, 0), K = 0.3) )
    X1     X2     X3     X4     X5     X6     X7     X8     X9    X10 
1.2953 1.2118 0.6190 1.0587 0.5811 1.6804 2.1016 0.3107 0.8781 1.2868

they are in the same order as the names of the list elements:

R> names(out)
 [1] "X1"  "X2"  "X3"  "X4"  "X5"  "X6"  "X7"  "X8"  "X9"  "X10"
R> names(ll)
 [1] "X1"  "X2"  "X3"  "X4"  "X5"  "X6"  "X7"  "X8"  "X9"  "X10"
R> all.equal(names(out), names(ll))
[1] TRUE

If you want something back that looks like the original list, then use lapply() instead

R> lapply(ll, function(x, K) max(x - K, 0), K = 0.3)
$X1
[1] 1.295

$X2
[1] 1.212

$X3
[1] 0.619

$X4
[1] 1.059

$X5
[1] 0.5811
....

However, it is not clear that you want the maximum or the parallel maximum, i.e. for each list element a vector retuning x - K or 0, whichever is larger, for each element of x. If you want this, that functionality is in the pmax() function:

R> lapply(ll, function(x, K) pmax(x - K, 0), K = 0.3)
$X1
 [1] 0.00000 0.00000 0.00000 1.29528 0.02951 0.00000 0.18743 0.43832 0.27578
[10] 0.00000

$X2
 [1] 1.21178 0.08984 0.00000 0.00000 0.82493 0.00000 0.00000 0.64384 0.52122
[10] 0.29390

$X3
 [1] 0.6190 0.4821 0.0000 0.0000 0.3198 0.0000 0.0000 0.0000 0.0000 0.1179

$X4
 [1] 1.05868 0.00000 0.08767 0.00000 0.00000 0.00000 0.00000 0.00000 0.80003
[10] 0.46318
....

or via sapply, which simplifies the reuslt to a matrix:

R> sapply(ll, function(x, K) pmax(x - K, 0), K = 0.3)
           X1      X2     X3      X4      X5      X6     X7     X8      X9
 [1,] 0.00000 1.21178 0.6190 1.05868 0.00000 0.09811 2.1016 0.1755 0.00000
 [2,] 0.00000 0.08984 0.4821 0.00000 0.00000 0.00000 0.0000 0.0000 0.00000
 [3,] 0.00000 0.00000 0.0000 0.08767 0.39696 0.04112 0.3897 0.3107 0.87809
 [4,] 1.29528 0.00000 0.0000 0.00000 0.25666 0.00000 0.0000 0.0000 0.00000
 [5,] 0.02951 0.82493 0.3198 0.00000 0.00000 1.13302 0.0000 0.0000 0.29395
 [6,] 0.00000 0.00000 0.0000 0.00000 0.00000 1.68040 0.0000 0.0000 0.03295
 [7,] 0.18743 0.00000 0.0000 0.00000 0.06458 0.00000 0.0000 0.0000 0.76310
 [8,] 0.43832 0.64384 0.0000 0.00000 0.46853 0.00000 1.1656 0.0000 0.00000
 [9,] 0.27578 0.52122 0.0000 0.80003 0.00000 0.26972 0.0000 0.0000 0.07002
[10,] 0.00000 0.29390 0.1179 0.46318 0.58111 0.00000 1.8726 0.0000 0.00000
         X10
 [1,] 0.0000
 [2,] 0.9079
 [3,] 0.8604
 [4,] 0.4002
 [5,] 1.2868
 [6,] 0.2585
 [7,] 0.0000
 [8,] 0.0000
 [9,] 0.0000
[10,] 0.0000

Finally, note that it is good practice to pass into your function all information it needs to run. You are relying on R finding K somewhere. It is much better to have your anonymous function take an argument K and pass along the value of K you wish to use when you call the function. This is what I did above in my examples, e.g.

lapply(ll, function(x, K) pmax(x - K, 0), K = 0.3)
           |___________ FUN ___________| |_ ARGS_|

where the bit I have marked with ARGS is where you supply any further arguments required by the function supplied to argument FUN.




回答2:


somelist <- list()

somelist[[1]] <- sample(1:100,5)
somelist[[2]] <- sample(1:100,10)
somelist[[3]] <- sample(1:100,15)

k <- 50

somelistmod <- lapply(somelist, function(x) pmax(0,x-k))

Output -

> somelist
[[1]]
[1] 58 27 80 51 57

[[2]]
 [1]  72  81  57  79   2  74 100  49  46  16

[[3]]
 [1]  29  24  37  45  26  25  67  61  63  62  30  69  92  89 100

> somelistmod
[[1]]
[1]  8  0 30  1  7

[[2]]
 [1] 22 31  7 29  0 24 50  0  0  0

[[3]]
 [1]  0  0  0  0  0  0 17 11 13 12  0 19 42 39 50

The main difference is that you need to use lapply instead of sapply, and pmax instead of max to get a pairwise comparison.




回答3:


Since you want to return a list, you should use lapply instead of sapply. Furthermore, the function max takes the maximum of your vector x. Use pmaxinstead:

lapply(data,function(x) pmax(x-K,0))



回答4:


You should replace sapply with lapply if you want to obtain a list:

lapply(data,function(x) max(x-K,0))


来源:https://stackoverflow.com/questions/20403985/apply-to-list-of-vectors

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!