How to apply a function to each element of a vecto

2019-06-19 08:18发布

问题:

Let's say I want to multiply each even element of a vector by 2 and each odd element of a vector by 3. Here is some code that can do this:

v <- 0:10

idx <- v %% 2 == 0
v[idx] <- v[idx] * 2
v[!idx] <- v[!idx] * 3

This would get difficult if I had more than two cases. It seems like the apply family of functions never deals with vectors so I don't know a better way to do this problem. Maybe using an apply function would work if I made transformations on the data, but it seems like that shouldn't be something that I would need to do to solve this simple problem.

Any ideas?

Edit: Sorry for the confusion. I am not specifically interested in the "%%" operator. I wanted to put some concrete code in my question, but, based on the responses to the question, was too specific. I wanted to figure out how to apply some arbitrary function to each member of the list. This was not possible with apply() and I thought sapply() only worked with lists.

回答1:

Easiest would be:

v*c(2,3) # as suggested by flodel in a comment.

The term to search for in the documentation is "argument recycling" ... a feature of the R language. Only works for dyadic infix functions (see ?Ops). For non-dyadcic vectorized functions that would not error out with some of the arguments and where you couldn't depend on the structure of "v" to be quite so regular, you could use ifelse:

ifelse( (1:length(v)) %% 2 == 0, func1(v), func2(v) )

This constructs two vectors and then chooses elements in the first or second based on the truth value of hte first argument. If you were trying to answer the question in the title of your posting then you should look at:

?sapply


回答2:

You can do:

v <- v * c(2, 3)[v %% 2 + 1]

It is generalizable to any v %% n, e.g.:

v <- v * c(2, 3, 9, 1)[v %% 4 + 1]

Also it does not require that length(v) be a multiple of n.



回答3:

You can use vector multiplication to do what you want:

tmp <- 1:10
tmp * rep(c(3,2), length(tmp)/2)

This is easy to extend to three or more cases:

tmp * rep(c(3,2,4), length(tmp)/3)


回答4:

Here is an answer allowing any set of arbitrary functions to be applied to defined groups within a vector.

# source data
test <- 1:9
# categorisations of source data
cattest <- rep(1:3,each=3)
#[1] 1 1 1 2 2 2 3 3 3

Make the function to differentially apply functions:

categ <- function(x,catg) {
          mapply(
                 function(a,b) {
                                switch(b,
                                       a * 2,
                                       a * 3,
                                       a / 2
                                      )
                               },
                  x,
                  catg
                 )
         }
# where cattest = 1, multiply by 2
# where cattest = 2, multiply by 3
# where cattest = 3, divide by 2

The result:

categ(test,cattest)
#[1]  2.0  4.0  6.0 12.0 15.0 18.0  3.5  4.0  4.5


标签: r vector apply