Reputation: 202
I want to create a function to sum two columns together, in which one word connects two columns and there are three sets. I want to pass that word as the only argument, and add a new column with that same name. Something like this.
the_first_x <- c(0,0,10,0)
the_second_x <- c(10,0,10,0)
the_first_y <- c(0,5,5,5)
the_second_y <- c(5,5,0,0)
df <- data.frame(the_first_x,
the_second_x,
the_first_y,
the_second_y)
summing <- function(letter){
df$letter <- the_first_letter + the_second_letter
}
Such that using the following adds a column with that letter as a name and that sum as its rows
summing(x)
summing(y)
By doing it like this, the letter
argument is not recognised, and using something like paste()
makes that the argument is surrounded by parentheses and also not recognised.
Upvotes: 0
Views: 50
Reputation: 50668
I would advise against using (1) <<-
and (2) deparse(substitute(...))
.
Concerning (1), this is advice taken from What is the difference between assign() and <<- in R? on what not to use <<-
for (addition in bracket is mine):
The Evil and Wrong use [of
<<-
] is to modify variables in the global environment.
Here is a tidyverse
option using some rlang
syntax:
library(tidyverse)
my_sum <- function(df, x) {
x <- enquo(x)
col <- names(df)[str_detect(names(df), quo_name(x))]
df %>% mutate(!!x := !!sym(col[1]) + !!sym(col[2]))
}
df %>% my_sum(x)
# the_first_x the_second_x the_first_y the_second_y x
#1 0 10 0 5 10
#2 0 0 5 5 0
#3 10 10 5 0 20
#4 0 0 5 0 0
df %>% my_sum(y)
# the_first_x the_second_x the_first_y the_second_y y
#1 0 10 0 5 5
#2 0 0 5 5 10
#3 10 10 5 0 5
#4 0 0 5 0 5
We can nicely chain multiple my_sum
calls:
df %>% my_sum(x) %>% my_sum(y)
# the_first_x the_second_x the_first_y the_second_y x y
#1 0 10 0 5 10 5
#2 0 0 5 5 0 10
#3 10 10 5 0 20 5
#4 0 0 5 0 0 5
Upvotes: 2
Reputation: 11480
Here is a better approach.
(one should avoid using <<-
where possible)
summing <- function(data, letter, pattern = paste0(letter,"$")){
data[[letter]] <- rowSums(data[,grepl(pattern,names(data),)], na.rm = T)
return(data)
}
This function is especially handy when working with a pipe:
library(magrittr)
df %>% summing("x") %>% summing("y")
# the_first_x the_second_x the_first_y the_second_y x y
#1 0 10 0 5 10 5
#2 0 0 5 5 0 10
#3 10 10 5 0 20 5
#4 0 0 5 0 0 5
Of course, you can use it without a pipe:
ans <- summing(df, "x")
summing(ans, "y")
The pattern
argument takes regular expression. With that, it's very general and specific to which columns you want to add.
Upvotes: 2