Pass string as name of attached data column name
Summary
In light of the various changes to the detail of the question, here are two solutions to the problem that can be phrased as:
Given
col_names <- c("Obj1$Var1", "Obj2$Var2")
how to return a data frame that would be the equivalent of
cbind(Obj1$Var1, Obj2$Var2)
?
The simplest solution would be
as.data.frame(sapply(col_names, function(x) eval(parse(text = x))))
but that uses parse()
which shouldn't be relied on for things like this. An alternative, but somewhat longer solution is
get4 <- function(x, ...) {
fun <- function(text, ...) {
obj <- get(text[1], ...)
obj[[text[2]]]
}
sx <- strsplit(x, "\\$")
lx <- lapply(sx, fun, ...)
out <- do.call(cbind.data.frame, lx)
names(out) <- x
out
}
get4(col_names)
The second solution has advantages, despite being somewhat longer, in that it
- will work for data of different types as it works with a list and converts that to a data frame. The
eval(parse(text = ....))
solution simplifies to an array first. Usinglapply()
instead ofsapply()
is an option that gets round this, but needs extra work to change thenames
of the resulting object. - uses common function
get()
to grab the object with stated name, and basic subsetting syntax. - doesn't use
parse
;-)
Original Answer
The original Answer with greater detail continues below:
eval(parse(....))
will work
data1 <- data.frame(column1 = 1:10, column2 = letters[1:10])
txt <- "data1$column2"
> eval(parse(text = txt))
[1] a b c d e f g h i j
Levels: a b c d e f g h i j
As @texb mentions, this can trivially be extended to handle a vector of strings via (modified to return a data frame)
col_names <- c("iris$Sepal.Length", "iris$Sepal.Width")
as.data.frame(sapply(col_names, function(x) eval(parse(text = x))))
It may be more acceptable to use get
but you'll have to do a bit of precessing, something along the lines of
get2 <- function(x, ...) {
sx <- strsplit(x, "\\$")[[1]]
obj <- get(sx[1], ...)
obj[[sx[2]]]
}
> get2(txt)
[1] a b c d e f g h i j
Levels: a b c d e f g h i j
iris
example from OP's question
As @texb mentions, the eval(parse(text = ....))
version can trivially be extended to handle a vector of strings via (modified to return a data frame)
col_names <- c("iris$Sepal.Length", "iris$Sepal.Width")
as.data.frame(sapply(col_names, function(x) eval(parse(text = x))))
iris$Sepal.Length iris$Sepal.Width
1 5.1 3.5
2 4.9 3.0
3 4.7 3.2
4 4.6 3.1
5 5.0 3.6
6 5.4 3.9
....
Modifiying get2()
is also possible to allow it to work on a vector of strings such as col_names
. Here I loop over the first elements of sx
to extract the object string (checking that there is only one unique object name), then I get
that object and then subset it using the variable names (extracted using sapply(sx, `[`, 2)
)
get3 <- function(x, ...) {
sx <- strsplit(x, "\\$")
obj <- unique(sapply(sx, `[`, 1))
stopifnot(length(obj) == 1L)
obj <- get(obj, ...)
obj[sapply(sx, `[`, 2)]
}
col_names <- c("iris$Sepal.Length", "iris$Sepal.Width")
head(get3(col_names))
> head(get3(col_names))
Sepal.Length Sepal.Width
1 5.1 3.5
2 4.9 3.0
3 4.7 3.2
4 4.6 3.1
5 5.0 3.6
6 5.4 3.9
If you have multiple objects referenced in col_names
then you will need a different solution, along the lines of
get4 <- function(x, ...) {
fun <- function(text, ...) {
obj <- get(text[1], ...)
obj[[text[2]]]
}
sx <- strsplit(x, "\\$")
lx <- lapply(sx, fun, ...)
out <- do.call(cbind.data.frame, lx)
names(out) <- x
out
}
col_names2 <- c("iris$Sepal.Length", "iris2$Sepal.Length")
get4(col_names2)
> head(get4(col_names2))
iris$Sepal.Length iris2$Sepal.Length
1 5.1 5.1
2 4.9 4.9
3 4.7 4.7
4 4.6 4.6
5 5.0 5.0
6 5.4 5.4
How to pass string as column name in R
We can use get
col= paste0(m,"_var1")
get(r)[col]
# jan_var1
#1 1
#2 2
#3 3
#4 4
#5 5
get(r)
would return the entire dataframe having name as jan5e_results
and from that we select col
column to subset.
# jan_var1 b
#1 1 6
#2 2 7
#3 3 8
#4 4 9
#5 5 10
data
jan5e_results <- data.frame(jan_var1 = 1:5, b = 6:10)
Passing string as column name in lag()
You may use !!
instead of {{}}
df %>%
mutate(!!new_col_name := lag(!!as.symbol(new_col_value)))
age value_2010 value_lag
1 1 10 NA
2 2 20 10
3 3 30 20
error in pass string as column name R t test
If you want to use srings in formulas you can use reformulate
.
Your example data has too few observations to work with a double grouped pairwise_t_test
, but the general notation would be as follows:
library(dplyr)
library(rstatix)
outcome_var <- "Sepal.Length"
grouping_var <- "Species"
iris %>%
pairwise_t_test(., reformulate(grouping_var, outcome_var), paired = FALSE, p.adjust.method = "holm")
#> # A tibble: 3 x 9
#> .y. group1 group2 n1 n2 p p.signif p.adj p.adj.signif
#> * <chr> <chr> <chr> <int> <int> <dbl> <chr> <dbl> <chr>
#> 1 Sepal.Le… setosa versic… 50 50 8.77e-16 **** 1.75e-15 ****
#> 2 Sepal.Le… setosa virgin… 50 50 2.21e-32 **** 6.64e-32 ****
#> 3 Sepal.Le… versico… virgin… 50 50 2.77e- 9 **** 2.77e- 9 ****
Created on 2020-07-08 by the reprex package (v0.3.0)
Is it possible to pass a string of column names to tidy-select?
You can use all_of
:
pivot_longer(df, cols = all_of(column),...)
From the tidyr
manual:
If you have a character vector of column names, use all_of() or
any_of(), depending on whether or not you want unknown variable names
to cause an error, e.g unnest(df, all_of(vars)), unnest(df,
-any_of(vars)).
Pass a string as variable name in dplyr::filter
!!
or UQ
evaluates the variable, so mtcars %>% filter(!!var == 4)
is the same as mtcars %>% filter('cyl' == 4)
where the condition always evaluates to false; You can prove this by printing !!var
in the filter function:
mtcars %>% filter({ print(!!var); (!!var) == 4 })
# [1] "cyl"
# [1] mpg cyl disp hp drat wt qsec vs am gear carb
# <0 rows> (or 0-length row.names)
To evaluate var
to the cyl
column, you need to convert var
to a symbol of cyl
first, then evaluate the symbol cyl
to a column:
Using rlang
:
library(rlang)
var <- 'cyl'
mtcars %>% filter((!!sym(var)) == 4)
# mpg cyl disp hp drat wt qsec vs am gear carb
#1 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1
#2 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2
#3 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2
# ...
Or use as.symbol/as.name
from baseR:
mtcars %>% filter((!!as.symbol(var)) == 4)
mtcars %>% filter((!!as.name(var)) == 4)
Can I pass a column name to a substring function using a variable?
No, you cannot do it that way. SQL normally has to know what columns you are working with for optimization. One way to do it would be to Have each column name in the where clause:
DELETE TOP (@Dimension)
FROM [dbo].[TestDelete]
WHERE (@ColumnName = 'DateReceived' and SUBSTRING(DateReceived, 1, 2) = @Year)
OR (@ColumnName = 'DateSent' and SUBSTRING(DateSent, 1, 2) = @Year)
Another way would be to use sp_executesql and create the delete as a string:
declare @sql nvarchar(max) = concat('DELETE TOP(@Dimension) ',
'FROM [dbo].[TestDelete] ',
'WHERE SUBSTRING(', @ColumnName, ', 1, 2) = @Year');
exec sp_executesql @sql,
N'@Dimension int', N'Year int',
@Dimension = @Dimension, @Year = @Year;
I don't think either is a good idea though. Why do you need the column name to be passed?
Related Topics
How to Join Data from 2 Different CSV-Files in R
Print the Sourced R File to an Appendix Using Sweave
Calculating the Distance Between Polygon and Point in R
How to Configure Box.Color in Directlabels "Draw.Rects"
System Is Computationally Singular: Reciprocal Condition Number in R
Plot Line on Top of Stacked Bar Chart in Ggplot2
No Dimensions of Non-Empty Numeric Vector in R
Plotly Adding a Source or Caption to a Chart
Note or Warning from Package Check When Readme.Md Includes Images
Installing R Studio with Anaconda
Adding Annotation (Segment/Arrow) in Only Certain Facet Ggplot
How to Add Main Title and Manipulating Axis Labels in Ggplot2 in Rstudio
Cumulative Sum in a Window (Or Running Window Sum) Based on a Condition in R
How to Make Join Operations in Dplyr Silent
Use Loop to Split a List into Multiple Dataframes
Trouble Installing "Sf" Due to "Gdal"
Extracting Output from Principal Function in Psych Package as a Data Frame