I have a dataframe with a set of objects df$data
and a set of rules to be applied on every object df$rules
.
df <- data.frame(
data = c(1,2,3),
rules = c("rule1", "rule1, rule2, rule3", "rule3, rule2"),
stringsAsFactors = FALSE
)
The rules are
rule1 <- function(data) {
data * 2
}
rule2 <- function(data) {
data + 1
}
rule3 <- function(data) {
data ^ 3
}
For every row in the dataframe I want to apply all the rules specified in the rules
column. The rules should be applied in series.
What I figured out:
apply_rules <- function(data, rules) {
for (i in 1:length(data)) {
rules_now <- unlist(strsplit(rules[i], ", "))
for (j in 1:length(rules_now)) {
data[i] <- apply_rule(data[i], rules_now[j])
}
}
return(data)
}
apply_rule <- function(data, rule) {
return(sapply(data, rule))
}
apply_rules(df$data, df$rules)
# [1] 2 125 28
Although this works I'm pretty sure there must be more elegant solutions. On SO I could find lot's of stuff about the apply
-functions and also one post about applying many functions to a vector and something about chaining functions. The Compose
idea looks promising but I couldn't figure out how to make a call to Compose
with my rules as string. (parse()
didn't work..)
Any hints?
You can work with functions as if they were objects. For example, you can assign functions to variables, to array elements, and to other objects. They can also be passed around as arguments to other functions or be returned from those functions. The only difference with objects is that functions can be called.
Methods—setting functions as properties of objects. In JavaScript, you can use functions as values, just like numbers, strings, and objects. That means you can pass them as arguments, return them from other functions, and set them as properties of objects.
The apply() method allows an object to borrow the method of another object without duplicating the code. The server object doesn't have the turnOn() and turnOff() methods. In this example, the server object borrows the turnOn() method of the computer object.
Some good answers already but throw in another option - build a pipe chain as a string then evaluate it. For example - for row 1 - eval(parse(text = "1 %>% rule1"))
gives 2
eval_chain <- function(df) {
eval(parse(text = paste(c(df$data, unlist(strsplit(df$rules, ", "))), collapse=" %>% ")))
}
df$value <- sapply(1:nrow(df), function(i) df[i, ] %>% eval_chain)
# data rules value
# 1 1 rule1 2
# 2 2 rule1, rule2, rule3 125
# 3 3 rule3, rule2 28
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With