lambda-like functions in R?
You have to look at the source of curve
to appreciate what is happening (just type curve
at the prompt and press enter).
There you can find how the expression passed is parsed.
The only way a function is discovered as being just that, is when only its name is passed along (see the is.name
part). If that is not the case, the expression is called for every x
. In your case: for every x
, the result is a function, which is not a happy thought for plotting...
So in short: no you cannot do what you tried, but as @ROLO indicated, you can immediately pass the function body, which will be parsed as an expression (and should contain x
). If this holds multiple statements, just enclose them in curly braces.
Is there a better clean approach to single-use functions in R?
You can use with
with a list or data-frame as first argument. For example:
result <- with(list(a=3, b=4), {
foo <- a + b
foo^2
})
This keeps the global environment clean, because the part enclosed in brackets is evaluated in a separate environment that is destroyed after the evaluation takes place.
However, in my experience it can become cumbersome to program in this style. Sometimes I find more practical to clean up unwanted objects with rm()
when they're no longer needed. It's not as elegant, this I agree.
Anonymous function in lapply
Instead of going over the data frame directly you could switch things around and have lapply go over a vector of the column names,
data(iris)
lapply(colnames(iris), function(x) c(class(iris[[x]]), x))
or over an index for the columns, referencing the data frame.
lapply(1:ncol(iris), function(x) c(class(iris[[x]]), names(iris[x])))
Notice the use of both single and double square brackets.iris[[n]]
references the values of the n
th object in the list iris
(a data frame is just a particular kind of list), stripping all attributes, making something like mean(iris[[1]])
possible.iris[n]
references the n
th object itself, all attributes intact, making something like names(iris[1])
possible.
What is a lambda (function)?
Lambda comes from the Lambda Calculus and refers to anonymous functions in programming.
Why is this cool? It allows you to write quick throw away functions without naming them. It also provides a nice way to write closures. With that power you can do things like this.
Python
def adder(x):
return lambda y: x + y
add5 = adder(5)
add5(1)
6
As you can see from the snippet of Python, the function adder takes in an argument x, and returns an anonymous function, or lambda, that takes another argument y. That anonymous function allows you to create functions from functions. This is a simple example, but it should convey the power lambdas and closures have.
Examples in other languages
Perl 5
sub adder {
my ($x) = @_;
return sub {
my ($y) = @_;
$x + $y
}
}
my $add5 = adder(5);
print &$add5(1) == 6 ? "ok\n" : "not ok\n";
JavaScript
var adder = function (x) {
return function (y) {
return x + y;
};
};
add5 = adder(5);
add5(1) == 6
JavaScript (ES6)
const adder = x => y => x + y;
add5 = adder(5);
add5(1) == 6
Scheme
(define adder
(lambda (x)
(lambda (y)
(+ x y))))
(define add5
(adder 5))
(add5 1)
6
C# 3.5 or higher
Func<int, Func<int, int>> adder =
(int x) => (int y) => x + y; // `int` declarations optional
Func<int, int> add5 = adder(5);
var add6 = adder(6); // Using implicit typing
Debug.Assert(add5(1) == 6);
Debug.Assert(add6(-1) == 5);
// Closure example
int yEnclosed = 1;
Func<int, int> addWithClosure =
(x) => x + yEnclosed;
Debug.Assert(addWithClosure(2) == 3);
Swift
func adder(x: Int) -> (Int) -> Int{
return { y in x + y }
}
let add5 = adder(5)
add5(1)
6
PHP
$a = 1;
$b = 2;
$lambda = fn () => $a + $b;
echo $lambda();
Haskell
(\x y -> x + y)
Java see this post
// The following is an example of Predicate :
// a functional interface that takes an argument
// and returns a boolean primitive type.
Predicate<Integer> pred = x -> x % 2 == 0; // Tests if the parameter is even.
boolean result = pred.test(4); // true
Lua
adder = function(x)
return function(y)
return x + y
end
end
add5 = adder(5)
add5(1) == 6 -- true
Kotlin
val pred = { x: Int -> x % 2 == 0 }
val result = pred(4) // true
Ruby
Ruby is slightly different in that you cannot call a lambda using the exact same syntax as calling a function, but it still has lambdas.
def adder(x)
lambda { |y| x + y }
end
add5 = adder(5)
add5[1] == 6
Ruby being Ruby, there is a shorthand for lambdas, so you can define adder
this way:
def adder(x)
-> y { x + y }
end
R
adder <- function(x) {
function(y) x + y
}
add5 <- adder(5)
add5(1)
#> [1] 6
Loop over character vectors and use elements as column names within lambda function
Those are strings. We need to convert to sym
bol and evaluate (!!
)
library(purrr)
library(dplyr)
out <- map(index, ~iris %>%
filter (!! rlang::sym(.x) > mean(!! rlang::sym(.x))))
names(out) <- index
-output
> str(out)
List of 2
$ Sepal.Length:'data.frame': 70 obs. of 5 variables:
..$ Sepal.Length: num [1:70] 7 6.4 6.9 6.5 6.3 6.6 5.9 6 6.1 6.7 ...
..$ Sepal.Width : num [1:70] 3.2 3.2 3.1 2.8 3.3 2.9 3 2.2 2.9 3.1 ...
..$ Petal.Length: num [1:70] 4.7 4.5 4.9 4.6 4.7 4.6 4.2 4 4.7 4.4 ...
..$ Petal.Width : num [1:70] 1.4 1.5 1.5 1.5 1.6 1.3 1.5 1 1.4 1.4 ...
..$ Species : Factor w/ 3 levels "setosa","versicolor",..: 2 2 2 2 2 2 2 2 2 2 ...
$ Sepal.Width :'data.frame': 67 obs. of 5 variables:
..$ Sepal.Length: num [1:67] 5.1 4.7 4.6 5 5.4 4.6 5 4.9 5.4 4.8 ...
..$ Sepal.Width : num [1:67] 3.5 3.2 3.1 3.6 3.9 3.4 3.4 3.1 3.7 3.4 ...
..$ Petal.Length: num [1:67] 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.5 1.5 1.6 ...
..$ Petal.Width : num [1:67] 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.1 0.2 0.2 ...
..$ Species : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
-testing with OP's expected
> expected <- list(Sepal.Length = iris %>% filter (Sepal.Length > mean(Sepal.Length)),
+ Sepal.Width = iris %>% filter (Sepal.Width > mean(Sepal.Width)))
>
> identical(out, expected)
[1] TRUE
Or subset with cur_data()
map(index, ~ iris %>%
filter(cur_data()[[.x]] > mean(cur_data()[[.x]])))
Or use across
or if_all
, which takes directly string
map(index, ~ iris %>%
filter(across(all_of(.x), ~ . > mean(.))))
Is there a way to invoke an AWS Lambda function within rShiny app?
Yes, this is a good use case for AWS Lambda. Lambda can be notified of a new object in S3, do whatever processing is required and write the output back.
Note: Double, triple check you are reading / writing to either different buckets or paths of a bucket and you don't create an infinite loop.
The Lambda function to make a call to AWS Simple Notification Service (SNS) to notify users that a task has finished after it has successfully written the data to S3.
If there are multiple users of this system then you might want to write a small manifest file to S3 which tells the Lambda function which data file to process and the email address of the person to notify.
The Lambda function would then just be triggered by the creation of the manifest.
What is the equivalent of \(x) in lower versions of r?
\
is a syntactic shortcut for the function
keyword starting with R 4.1.0. From the documentation:
function( arglist ) expr
\( arglist ) expr
In fact, we can verify the syntactic equivalence ourselves by looking at an unevaluated expression:
quote(\(arglist) expr)
# function(arglist) expr
Why don't lambda functions handle replacement functions in their intuitive form?
Whenever you do an assignment in R, the value returned from that expression is the right hand side value. This is true even for "special" versions of assign functions. For example if you do this
x <- 1:2; y <- (names(x) <- letters[1:2])
> y
[1] "a" "b"
You can see that y
gets the values of the names, not the updated value of x
.
In your case if you want to return the updated value itself, you need to do so explicitly
lapply(a, function(x) {length(x) <- mx; x})
Related Topics
What Is the Most Useful R Trick
How to Call a Function Using the Character String of the Function Name in R
Using Stargazer with Rstudio and Knitr
How to Select Last N Observation from Each Group in Dplyr Dataframe
Databricks Configure Using Cmd and R
Rmarkdown: How to Change the Font Color
Align Multiple Tables Side by Side
Determining Utm Zone (To Convert) from Longitude/Latitude
Set Margin Size When Converting from Markdown to PDF with Pandoc
Finding 2 & 3 Word Phrases Using R Tm Package
How to Insert an Image into the Navbar on a Shiny Navbarpage()
Output a Vector in R in the Same Format Used for Inputting It into R