Applying Over a Vector of Functions

How to use apply over a vector?

First note that even the numbers in col2 are character since when combined with other elements which are character they get coerced to character.

str(a)
## 'data.frame': 6 obs. of 2 variables:
## $ col1: int 1 2 3 4 5 6
## $ col2: chr "a" "b" "1" "c" ...

1) grepl thus we should use character processing like this:

grepl("^\\d+$", a$col2)
## [1] FALSE FALSE TRUE FALSE TRUE TRUE

grepl is alredy vectorized so we don't need an apply or related function to iterate over the elements of col2.

2) (s)apply These also work but seems unnecessarily involved given that grepl alone works:

sapply(a$col2, grepl, pattern = "^\\d+$")
## a b 1 c 2 3
## FALSE FALSE TRUE FALSE TRUE TRUE

apply(array(a$col2), 1, grepl, pattern = "^\\d+$")
## [1] FALSE FALSE TRUE FALSE TRUE TRUE

3) type.convert Another approach is to use type.convert which will convert to numeric if it can be represented as one. Then we can use is.numeric.

sapply(a$col2, function(x) is.numeric(type.convert(x)))
## a b 1 c 2 3
## FALSE FALSE TRUE FALSE TRUE TRUE

Applying a simple function over a vector using vapply

Your function has a bug in it. Instead of

Fun = function(x) x[x<0]=0

You actually want:

correct_fun = function(x){
x[x<0]=0
return(x)
}

As is, your function is not returning anything at the moment. It modifies x but doesn't return it so it just dies with the function. Executing correct_fun on A I get:

[1]  0  0  0  0  0  0  0  0  0  0  0  1  2  3  4  5  6  7  8  9 10

Apply function over two vectors of different lengths, and return a matrix in R

Try this

library(stringr)
t(sapply(names,str_detect,pattern=slices))

You can also do this in base R using grepl

sapply(slices, grepl, names)

How do I apply this for loop over my character vector and output another vector?

The out is not initialized in the function

concat <- function(vector,SID){
out <- character(length(vector))

decrement_append <- "&decrementQuotas=true"
SID_append <- "?surveyId="

for(i in 1:length(vector)){
out[i] <- paste0(v[i],SID_append,SID,decrement_append)
}
out
}

-testing

> concat(v, "SV_55tYjKDRKYTRNIh")
[1] "R_2wmKOSbPWHl4VtT2?surveyId=SV_55tYjKDRKYTRNIh&decrementQuotas=true" "R_2TtslLEVNeHs2r73?surveyId=SV_55tYjKDRKYTRNIh&decrementQuotas=true"
[3] "R_ZF79IJ60LaxxsuR4?surveyId=SV_55tYjKDRKYTRNIh&decrementQuotas=true" "R_3JJDUkrZ07eIwnh5?surveyId=SV_55tYjKDRKYTRNIh&decrementQuotas=true"
[5] "R_3JrWuv9fsLK6qNx6?surveyId=SV_55tYjKDRKYTRNIh&decrementQuotas=true"

paste/paste0 are vectorized. So, looping is not really needed

concat2 <- function(vector,SID){


decrement_append <- "&decrementQuotas=true"
SID_append <- "?surveyId="


paste0(v, SID_append,SID,decrement_append)


}

-testing

> concat2(v, "SV_55tYjKDRKYTRNIh")
[1] "R_2wmKOSbPWHl4VtT2?surveyId=SV_55tYjKDRKYTRNIh&decrementQuotas=true" "R_2TtslLEVNeHs2r73?surveyId=SV_55tYjKDRKYTRNIh&decrementQuotas=true"
[3] "R_ZF79IJ60LaxxsuR4?surveyId=SV_55tYjKDRKYTRNIh&decrementQuotas=true" "R_3JJDUkrZ07eIwnh5?surveyId=SV_55tYjKDRKYTRNIh&decrementQuotas=true"
[5] "R_3JrWuv9fsLK6qNx6?surveyId=SV_55tYjKDRKYTRNIh&decrementQuotas=true"

Clojure iteration over vector of functions

It helps to not think in "code being executed" , but in "expression trees being reduced". Expression trees are rewritten until the result appears. Symbols are replaced by "what they stand for" and functions are applied to their arguments when a "live function" appears in the first position of a list; as in (some-function a b c). This is done in top-down fashion from the top of the expression tree to the leaves, stopping when the quote symbol is encountered.

In the example below, we unfortunately cannot mark what has already been reduced and what not as there is no support for coloring. Note that the order of reduction is not necessarily the one corresponding to what the compiled code issued by the Clojure compiler actually would do.

Starting with:

(defn stats
[numbers]
(map #(% numbers) [sum count avg]))

...we shall call stats.

First difficulty is that stats can be called with a collection as a single thing:

(stats [a0 a1 a2 ... an])

or it could be called with a series of values:

(stats a0 a1 a2 ... an)

Which is it? Unfortunately the expected calling style can only be found by looking at the function definition. In this case, the definition says

(defn stats [numbers] ...

which means stats expects a single thing called numbers. Thus we call it like this:

(stats [3 4 10])

Now reduction starts! The vector of numbers that is the argument is reduced to itself because every element of a vector is reduced and a number reduces to itself. The symbol stats is reduced to the function declared earlier. The definition of stats is actually:

(fn [numbers] (map #(% numbers) [sum count avg]))

...which is a bit hidden by the defn shorthand. Thus

(stats [3 4 10])

becomes

((fn [numbers] (map #(% numbers) [sum count avg])) [3 4 10])

Next, reducing the fn expression yields a live function of one argument. Let's mark the live function with a ★ and let's use mathematical arrow notation:

(★(numbers ➜ (map #(% numbers) [sum count avg])) [3 4 10])

The live function is on first position of the list, so a function call will follow. The function call consists in replacing the occurrence of numbers by the argument [3 4 10] in the live function's body and stripping the outer parentheses of the whol expression:

(map #(% [3 4 10]) [sum count avg])

Symbols map, sum, count, avg resolve to known, defined functions, where map and count come from the Clojure core library, and the rest has been defined earlier. Again, we mark them as live:

(★map #(% [3 4 10]) [★sum ★count ★avg]))

Again, the # % notation is a shorthand for a function taking one argument and inserting it into the % position, let's make this evident:

(★map (fn [x] (x [3 4 10])) [★sum ★count ★avg]))

Reducing the fn expression yields a live function of one argument. Again, mark with ★ and let's use mathematical arrow notation:

(★map ★(x ➜ (x [3 4 10])) [★sum ★count ★avg]))

A live function ★map is in head position and thus the whole expression is reduced according to the specification of map: apply the first argument, a function, to every element of the 2nd argument, a collection. We can assume the collection is created first, and then the collection members are further evaluated, so:

[(★(x ➜ (x [3 4 10])) ★sum)
(★(x ➜ (x [3 4 10])) ★count)
(★(x ➜ (x [3 4 10])) ★avg)]

Every element of the collection can be further reduced as each has a live function of 1 argument in head position and one argument available. Thus in each case, x is appropriately substituted:

[(★sum [3 4 10])
(★count [3 4 10])
(★avg [3 4 10])]

Every element of the collection can be further reduced as each has a live function of 1 argument in head position. The exercise continues:

[ ((fn [x] (reduce + x)) [3 4 10])
(★count [3 4 10])
((fn [x] (/ (sum x) (count x))) [3 4 10])]

then

[ (★(x ➜ (reduce + x)) [3 4 10])
3
(★(x ➜ (/ (sum x) (count x))) [3 4 10])]

then

[ (reduce + [3 4 10])
3
(/ ((fn [x] (reduce + x)) [3 4 10]) (count [3 4 10]))]

then

[ (★reduce ★+ [3 4 10])
3
(/ (*(x ➜ (reduce + x)) [3 4 10]) (count [3 4 10]))]

then

[ (★+ (★+ 3 4) 10)
3
(/ (reduce + [3 4 10]) (count [3 4 10]))]

then

[ (★+ 7 10)
3
(★/ (★reduce ★+ [3 4 10]) (★count [3 4 10]))]

then

[ 17
3
(★/ 17 3)]

finally

[ 17
3
17/3]

You can also use function juxt. Try (doc juxt) on the REPL:

clojure.core/juxt
([f] [f g] [f g h] [f g h & fs])
Takes a set of functions and returns a fn that is the juxtaposition
of those fns. The returned fn takes a variable number of args, and
returns a vector containing the result of applying each fn to the
args (left-to-right).
((juxt a b c) x) => [(a x) (b x) (c x)]

Let's try that!

(def sum #(reduce + %))
(def avg #(/ (sum %) (count %)))
((juxt sum count avg) [3 4 10])
;=> [17 3 17/3]
((juxt sum count avg) [80 1 44 13 6])
;=> [144 5 144/5]

And thus we can define stats alternatively as

(defn stats [numbers] ((juxt sum count avg) numbers))
(stats [3 4 10])
;=> [17 3 17/3]
(stats [80 1 44 13 6])
;=> [144 5 144/5]

P.S.

Sometimes Clojure-code is hard to read because you don't know what "stuff" you are dealing with. There is no special syntactic marker for scalars, collections, or functions and indeed a collection can appear as a function, or a scalar can be a collection. Compare with Perl, which has notation $scalar, @collection, %hashmap, function but also $reference-to-stuff and $$scalarly-dereferenced-stuff and @$collectionly-dereferenced-stuff and %$hashmapply-dereferenced-stuff).

Apply many functions to one vector

Similar to @CathG's comment, but without get:

v <- rnorm(10)
funs <- list(mean, median, sd)
sapply(funs, function(fun, x) fun(x), x = v)

Or with do.call:

sapply(funs, do.call, args = list(v))

How do you apply a function to each element of a dataset vector, and then return that vector?

R is manipulating vectors so, if v is a vector, you can directly pass your equation as follow:

v2 <- 1 - exp(-v*theta)

And it will be apply to each element of v and stored it in v2 object (which will also be a vector).

here an example:

v <- 1:10
theta = 5

> 1 - exp(-v*theta)

[1] 0.9932621 0.9999546 0.9999997 1.0000000 1.0000000 1.0000000 1.0000000 1.0000000 1.0000000 1.0000000


Related Topics



Leave a reply



Submit