问题
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