Я пишу блестящие приложения, которые берут объект (в основном фотографию или матрицу чисел) и создают набор графиков для исследования объекта. Я хочу настроить блестящее приложение как функцию, чтобы я мог вызывать его из командной строки и напрямую передавать ему интересующий объект. Я хотел бы иметь возможность возвращать имя объекта в названиях графиков и т.д. Я могу сделать это с помощью replace() за пределами блестящего приложения, но когда я помещаю его в блестящее приложение, оно возвращает имя объекта «внутри области действия» блестящей функции, а не имя объекта, который был передан в блестящая функция.
По предложению я использовал стилизатор для улучшения стиля кода:
#this puts Children in the title of the graph which is what I want but I want a shiny app:
myPlot <- function(x) {
plot(1:10, main = substitute(x))
}
children <- "10"
myPlot(children)
#when I do it inside the shiny App
#this puts x in the title of the plot which is not what I want:
require(shiny)
app1 <- function(x) {
shinyApp(
ui = mainPanel(plotOutput("plot1")),
server = function(input, output) {
output$plot1 <- renderPlot(myPlot(x))
}
)
}
app1(children)
Перед пакетом стайлера:
#this puts Children in the title of the graph which is what I want but I want a shiny app:
myPlot = function(x){
plot(1:10,main=substitute(x))
}
children = "10"
myPlot(children)
#when I do it inside the shiny App
#this puts x in the title of the plot which is not what I want:
app1 = function(x) {shinyApp(
ui = mainPanel(plotOutput("plot1")) ,
server = function(input,output){output$plot1 <- renderPlot( plot(1:10,main=substitute(x)) )}
)}
app1(children)
Ты можешь сделать:
app1 = function(x) {
title <- substitute(x)
shinyApp(
ui = mainPanel(plotOutput("plot1")),
server = function(input, output){
output$plot1 <- renderPlot( plot(1:10, main = title) )
}
)
}
Функция substitute очень полезна, но с ней нужно быть осторожным. Второй аргумент substitute — это env, и его можно соответствующим образом обновить, чтобы функция работала в любом месте.
fun <- function(x) substitute(expr = x, env = environment()) # current env is environment()
# you can control the scope of the substitute
# the parent.frame give us access to the nth previous env
fun_deep2 <- function(x) {
fun_temp <- function(x) {
substitute(expr = x, env = parent.frame(n = 1))
}
fun_temp(x)
}
fun(hey)
fun_deep2(hey)
Пожалуйста, попробуйте стилизовать свой код, прежде чем делиться, например. с styler пакетом. С другой стороны, старайтесь следовать базовым правилам программирования, таким как DRY , повторное использование и другим. Принимать это во внимание substitute может быть неправильным направлением. Дополнительный аргумент для имени может быть правильным. Пример того, почему замена, которая используется даже многими базовыми статистическими функциями R, опасна.
X = 1:10; y = 1:10; do.call(t.test, list(x = x, y = y)) или do.call(t.test, list(x = 1:10, y = 1:10))
Мы получаем совершенно другие имена, чем мы ожидали. Таким образом, любая функция, использующая замену, не может быть использована так просто в автоматическом режиме, как с помощью do.call.
Попробуйте представить, что у нас есть набор функций и набор аргументов, мы не знаем, какую функцию нам нужно использовать, и то же самое для аргументов. Затем мы используем do.call, так как сама функция является аргументом, тогда легко получить неожиданный результат для замены. С другой стороны, даже прямое использование опасно, как t.test(x = rnorm(10**3), y = rnorm(10**3)) # data: rnorm(10^3) and rnorm(10^3) # rnorm(10^3) is not very informative.
Я попробовал это, и, похоже, это сработало, как задумано. Все еще не соответствует матрице1 <- cbind(rnorm(100), rnorm(100)) matrix2 <- cbind(matrix1[, 1], matrix1[, 1] + 1) wrapTest2 <- function(test, xy) { x <- xy[, 1] y <- xy[, 2] result1 <- data.frame( object = paste(substitute(xy)), test = paste(substitute(test)), result = do.call(test, list( x = x, y = y))[[1]] ) return(result1) } wrapTest2(t.test,matrix1) wrapTest2(t.test,matrix2) wrapTest2(cor,matrix1) wrapTest2(cor,matrix2)
Поскольку вы не распечатали результаты теста, вы их еще не видели. x <- rnorm(100) y <- rnorm(100) wrapTest2 <- function(test, x, y) { do.call(test, list(x = x, y = y)) } wrapTest2(t.test,x, y)
Я вижу это сейчас: x2 <- rnorm(100) y2 <- rnorm(100) wrapTest2 <- function(test, x, y) { do.call(test, list(x = x, y = y)) } wrapTest2 (t.test,x2, y2) дает «среднее значение x» в печати, когда требуется «среднее значение x2». Я заранее Спасибо.
Я обновил код по вашему предложению. Не знал про пакет styler, спасибо. Я не слежу за вами в do.call(), не могли бы вы уточнить.