2

Example data:

> DF
   A  B  C
1 11 22 88
2 11 22 47
3  2 30 21
4  3 30 21

> r
[1] "A==A[i] & B==B[i] "           "A==A[i] & C==C[i] "          
[3] "B==B[i] & C==C[i] "           "A==A[i] & B==B[i] & C==C[i] "

Executed code:

> output=list()
> for (j in r){
+   for (i in 1:nrow(DF)){
+    
+     output[[j]][i]=j  
+   }
+ }
> output
$`A==A[i] & B==B[i] `
[1] "A==A[i] & B==B[i] " "A==A[i] & B==B[i] " "A==A[i] & B==B[i] "
[4] "A==A[i] & B==B[i] "

$`A==A[i] & C==C[i] `
[1] "A==A[i] & C==C[i] " "A==A[i] & C==C[i] " "A==A[i] & C==C[i] "
[4] "A==A[i] & C==C[i] "

$`B==B[i] & C==C[i] `
[1] "B==B[i] & C==C[i] " "B==B[i] & C==C[i] " "B==B[i] & C==C[i] "
[4] "B==B[i] & C==C[i] "

$`A==A[i] & B==B[i] & C==C[i] `
[1] "A==A[i] & B==B[i] & C==C[i] " "A==A[i] & B==B[i] & C==C[i] "
[3] "A==A[i] & B==B[i] & C==C[i] " "A==A[i] & B==B[i] & C==C[i] "

> output=purrr::flatten_chr(output)
> output
 [1] "A==A[i] & B==B[i] "           "A==A[i] & B==B[i] "          
 [3] "A==A[i] & B==B[i] "           "A==A[i] & B==B[i] "          
 [5] "A==A[i] & C==C[i] "           "A==A[i] & C==C[i] "          
 [7] "A==A[i] & C==C[i] "           "A==A[i] & C==C[i] "          
 [9] "B==B[i] & C==C[i] "           "B==B[i] & C==C[i] "          
[11] "B==B[i] & C==C[i] "           "B==B[i] & C==C[i] "          
[13] "A==A[i] & B==B[i] & C==C[i] " "A==A[i] & B==B[i] & C==C[i] "
[15] "A==A[i] & B==B[i] & C==C[i] " "A==A[i] & B==B[i] & C==C[i] "

My target was to get the same output with the specific values A[i], B[i] and C[i] from DF, i.e., the final output would be the following:

> output
[1] "A==11 & B==22 "            "A==11 & B==22 "          
[3] "A==2 & B==30 "             "A==3 & B==30 "          
[5] "A==11 & C==88 "            "A==11 & C==47 "          
[7] "A==2 & C==21 "             "A==3 & C==21 "          
[9] "B==22 & C==88 "            "B==22 & C==47 "          
[11] "B==30 & C==21 "           "B==30 & C==21 "          
[13] "A==11 & B==22 & C==88 "   "A==11 & B==22 & C==47 "
[15] "A==2 & B==30 & C==21 "    "A==3 & B==30 & C==21 "

I would be grateful if someone could help me with this matter.

2 Answers 2

2

The difficulty here comes from the way the problem is specified with the r vector, and it would be possible to modify Milan's answer to better match the expected result.

r <- c(
  "A==A[i] & B==B[i]", 
  "A==A[i] & C==C[i]",
  "B==B[i] & C==C[i]", 
  "A==A[i] & B==B[i] & C==C[i]"
)

Instead of that, I'll take another route, given that in each element of r, you only need to identify the names of the columns. For example, on the first case, you only need A and B.

library(purrr)
library(glue)
library(rlang)
names <- c("A", "B")
DF <- data.frame(
  A = c(11, 11, 2, 3),
  B = c(22, 22, 30, 30),
  C = c(88, 47, 21, 21)
)

map( names, ~{
  glue( "{name} == {values}", name = ., values = DF[[.]] )
})
#> [[1]]
#> A == 11
#> A == 11
#> A == 2
#> A == 3
#> 
#> [[2]]
#> B == 22
#> B == 22
#> B == 30
#> B == 30

you can then reduce it to only get one string per line of your data frame:

map( names, ~{
  glue( "{name} == {values}", name = ., values = DF[[.]] )
}) %>% 
  reduce( paste, sep = " & ")
#> [1] "A == 11 & B == 22" "A == 11 & B == 22" "A == 2 & B == 30" 
#> [4] "A == 3 & B == 30"

Wrapping it all up into a function that uses tidy eval to get the names to begin with:

tests <- function(data, ...){
  names <- map_chr(quos(...), f_name)

  map( names, ~{
    glue( "{name} == {values}", name = ., values = data[[.]] )
  }) %>% 
    reduce(paste, sep = " & " )

}

So that you can get the results by calling tests 4 times:

c(
  tests( DF, A, B), 
  tests( DF, A, C), 
  tests( DF, B, C), 
  tests( DF, A, B, C)
)
#>  [1] "A == 11 & B == 22"           "A == 11 & B == 22"          
#>  [3] "A == 2 & B == 30"            "A == 3 & B == 30"           
#>  [5] "A == 11 & C == 88"           "A == 11 & C == 47"          
#>  [7] "A == 2 & C == 21"            "A == 3 & C == 21"           
#>  [9] "B == 22 & C == 88"           "B == 22 & C == 47"          
#> [11] "B == 30 & C == 21"           "B == 30 & C == 21"          
#> [13] "A == 11 & B == 22 & C == 88" "A == 11 & B == 22 & C == 47"
#> [15] "A == 2 & B == 30 & C == 21"  "A == 3 & B == 30 & C == 21"
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you very much, Romain. I have run the code but I have got "Error in as_function(.f, ...) : object 'f_name' not found". I have done something wrong, I guess. Could you show me the way to solve this?
I probably should have loaded rlang too. I have added library(rlang) just now.
Thank you ever so much, Romain. It works very well. Now, I have to think and work about doing this with any number of columns, i.e. for any big dataframe input, but this would be another potencial question. I have selected your answer as the best right answer. Please, let me know if I have to do something else.
0

Is this output what you are after?

DF <- data.frame(A = c(11, 11, 2, 3),
                 B = c(22, 22, 30, 30),
                 C = c(88, 47, 21, 21))

r <- c("A==A[i] & B==B[i]", "A==A[i] & C==C[i]",
       "B==B[i] & C==C[i]", "A==A[i] & B==B[i] & C==C[i]")

output=list()
for (j in r){
  for (i in 1:nrow(DF))
    output[[j]][[i]] <- DF[with(DF, eval(parse(text = j))), ]
}

output

$`A==A[i] & B==B[i]`
$`A==A[i] & B==B[i]`[[1]]
   A  B  C
1 11 22 88
2 11 22 47

$`A==A[i] & B==B[i]`[[2]]
   A  B  C
1 11 22 88
2 11 22 47

$`A==A[i] & B==B[i]`[[3]]
  A  B  C
3 2 30 21

$`A==A[i] & B==B[i]`[[4]]
  A  B  C
4 3 30 21


$`A==A[i] & C==C[i]`
$`A==A[i] & C==C[i]`[[1]]
   A  B  C
1 11 22 88
...

2 Comments

Or perhaps surround the expression with a with( DF ) to avoid the risky gsub, e.g. output[[j]][i] <- DF[ with(DF, eval(parse(text=j))), ]
Thank you very much. I am afraid my question was not asked in the right way, so that I have explained it better.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.