Home > Back-end >  Apply function to and output to file individual lines of dataframe
Apply function to and output to file individual lines of dataframe

Time:12-10

I have exam questions structured in an Excel sheet, I need to export them in the format required by the exam package, in my case one Rnw file for each question. I managed to do what I need using a loop, I was wondering about alternatives to loops (e.g., create a function and then use with some implementation of *apply or purrr::map?). Here is my code, in real life the dataframe will be imported from Excel and will contain several hundreds of lines.

library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
library(glue)
#> 
#> Attaching package: 'glue'
#> The following object is masked from 'package:dplyr':
#> 
#>     collapse

questions <- data.frame(
  text = c("A question", "Another question"),
  a1 = rep("Option1", 2),
  a2 = rep("Option2", 2),
  a3 = rep("Option3", 2),
  a4 = rep("Option4", 2),
  correct = c(1,3),
  label = c("Question_1", "Question_2")
)

for(i in 1:nrow(questions)){
    q <- slice(questions, i)
    solutions <- paste(q$correct == 1:4, collapse=", ") |> noquote()
    sink(file=paste0(q$label, ".Rnw"))
    glue("\\begin{{question}}\n
    {q$text}\n
    <<echo=FALSE, results=hide, results=tex>>=
    questions=c('{q$a1}', '{q$a2}', '{q$a3}', '{q$a4}')
    solutions <- c({solutions})
    answerlist(questions)
    @\n
    \\end{{question}}") |> print()
    sink()
}

Created on 2021-12-09 by the reprex package (v2.0.1)

CodePudding user response:

It's quite easy with map. All you have to do is place the code between the loop into a function:

f = function(i) {
  q <- slice(questions, i)
  solutions <- paste(q$correct == 1:4, collapse=", ") %>% noquote()
  sink(file=paste0(q$label, ".Rnw"))
  glue("\\begin{{question}}\n
    {q$text}\n
    <<echo=FALSE, results=hide, results=tex>>=
    questions=c('{q$a1}', '{q$a2}', '{q$a3}', '{q$a4}')
    solutions <- c({solutions})
    answerlist(questions)
    @\n
    \\end{{question}}") %>% print()
  sink()
}

Then you can call it in map:

map(1:nrow(questions), f)

Or

1:nrow(questions) %>% map(f)

Or with lapply:

lapply(1:nrow(questions), f)
  • Related