我正在尝试对dataframe
中的被动shiny
进行一些转换。我想在下面的代码中将函数euc.dist
用于反应数据框bathy_new()
。
以下是可重现的例子:
library(shiny)
ui <- fluidRow(
numericInput(inputId = "n", "Group ", value = 1),
plotOutput(outputId = "plot")
)
server <- function(input, output){
bathy <- structure(list(`Corrected Time` = structure(c(
1512040500, 1512040500,
1512040501, 1512040502, 1512040502, 1512040503
), class = c(
"POSIXct",
"POSIXt"
), tzone = "UTC"), Longitude = c(
-87.169858, -87.169858,
-87.1698618, -87.1698652, -87.1698652, -87.16986785
), Latitude = c(
33.7578743,
33.7578743, 33.75788237, 33.75789018, 33.75789018, 33.75789717
), `Depth (m)` = c(
3.95096, 3.82296, 3.63096, 3.57096, 3.48096,
3.32096
), easting = c(
484269.60819222, 484269.60819222, 484269.257751374,
484268.944306767, 484268.944306767, 484268.700169299
), northing = c(
3735323.04565401,
3735323.04565401, 3735323.94098565, 3735324.80742908, 3735324.80742908,
3735325.58284154
), diff = c(0, 0, 0, 0, 0, 0), group = c(
1, 1,
1, 2, 2, 2
)), .Names = c(
"Corrected Time", "Longitude", "Latitude",
"Depth (m)", "easting", "northing", "diff", "group"
), row.names = c(
NA,
-6L
), class = c("tbl_df", "tbl", "data.frame"))
euc.dist <- function(x1, y1, x2, y2){
distance <- sqrt((x2-x1)^2 + (y2-y1)^2)
return(distance)
}
#
bathy_new <- reactive({
bathy %>% dplyr::filter(group == input$n)
})
test <- bathy_new()
dist <- NULL
for (i in 1:nrow(test)){
dist <- euc.dist(x1 = test[i, "easting"] %>% .$easting,
y1 = test[i, "northing"] %>% .$northing,
x2 = test[i+1, 'easting'] %>% .$easting,
y2 = test[i+1, 'northing'] %>% .$northing)
}
test$dist <- dist
output$plot <- renderPlot(
qplot(cumsum(test$dist), bathy_new()$`Depth (m)`)
)
}
shinyApp(ui, server)
这里的数据与原始数据相比是非常小的数据。但目标是找到每组中各点之间的eucledian距离。在这个小数据集中,我有两组; 1和2.
我一直收到以下错误
Error in .getReactiveEnvironment()$currentContext() :
Operation not allowed without an active reactive context. (You tried to do something that can only be done from inside a reactive expression or observer.)
我可以在闪亮之外运行此代码,但不确定如何处理反应数据。
这是存在错误的代码块:
test <- bathy_new()
dist <- NULL
for (i in 1:nrow(test)){
dist <- euc.dist(x1 = test[i, "easting"] %>% .$easting,
y1 = test[i, "northing"] %>% .$northing,
x2 = test[i+1, 'easting'] %>% .$easting,
y2 = test[i+1, 'northing'] %>% .$northing)
}
test$dist <- dist
最后,我想绘制累积距离cum(dist)
和深度Depth (m)
。
答案 0 :(得分:2)
您收到该错误的原因是您实际上尝试将reactive
分配给变量test
。这只能在反应性表达或观察者内部完成。
因此,您需要做的是将该代码置于反应式表达式中,例如renderPlot
。
output$plot <- renderPlot({
test <- bathy_new()
dist <- NULL
for (i in 1:(nrow(test) - 1)){
dist <- euc.dist(x1 = test[i, "easting"] %>% .$easting,
y1 = test[i, "northing"] %>% .$northing,
x2 = test[i+1, 'easting'] %>% .$easting,
y2 = test[i+1, 'northing'] %>% .$northing)
}
test$dist <- dist
qplot(cumsum(test$dist), bathy_new()$`Depth (m)`)
})
这应该摆脱错误,但我认为你的for
循环也可能有问题。您遍历1:nrow(test)
,但在循环内使用i+1
进行计算。因为这将是NA
,因此你的情节不会显示任何东西。
我修改了你的循环以迭代1:(nrow(test) - 1)
以获得有效的结果。
我还想指出Shiny
的工作方式。 Shiny在服务器函数之外运行代码每个R进程一次,然后在服务器函数每个连接一次内运行代码。然后,每当他们的依赖关系发生变化>时,就会出现的反应。
有关更多帮助,请参阅this topic
因此,最好在server
函数之外定义数据和函数,因为它们只需要运行一次。如果它们位于server
函数内,则每次新用户连接到应用程序时都会运行它们,但它效率不高。
完整代码:
library(shiny)
library(magrittr)
library(ggplot2)
bathy <- structure(list(`Corrected Time` = structure(c(
1512040500, 1512040500,
1512040501, 1512040502, 1512040502, 1512040503
), class = c(
"POSIXct",
"POSIXt"
), tzone = "UTC"), Longitude = c(
-87.169858, -87.169858,
-87.1698618, -87.1698652, -87.1698652, -87.16986785
), Latitude = c(
33.7578743,
33.7578743, 33.75788237, 33.75789018, 33.75789018, 33.75789717
), `Depth (m)` = c(
3.95096, 3.82296, 3.63096, 3.57096, 3.48096,
3.32096
), easting = c(
484269.60819222, 484269.60819222, 484269.257751374,
484268.944306767, 484268.944306767, 484268.700169299
), northing = c(
3735323.04565401,
3735323.04565401, 3735323.94098565, 3735324.80742908, 3735324.80742908,
3735325.58284154
), diff = c(0, 0, 0, 0, 0, 0), group = c(
1, 1,
1, 2, 2, 2
)), .Names = c(
"Corrected Time", "Longitude", "Latitude",
"Depth (m)", "easting", "northing", "diff", "group"
), row.names = c(
NA,
-6L
), class = c("tbl_df", "tbl", "data.frame"))
euc.dist <- function(x1, y1, x2, y2){
distance <- sqrt((x2-x1)^2 + (y2-y1)^2)
return(distance)
}
ui <- fluidRow(
numericInput(inputId = "n", "Group ", value = 1),
plotOutput(outputId = "plot")
)
server <- function(input, output){
bathy_new <- reactive({
bathy %>% dplyr::filter(group == input$n)
})
output$plot <- renderPlot({
test <- bathy_new()
dist <- NULL
for (i in 1:(nrow(test) - 1)){
dist <- euc.dist(x1 = test[i, "easting"] %>% .$easting,
y1 = test[i, "northing"] %>% .$northing,
x2 = test[i+1, 'easting'] %>% .$easting,
y2 = test[i+1, 'northing'] %>% .$northing)
}
test$dist <- dist
qplot(cumsum(test$dist), bathy_new()$`Depth (m)`)
})
}
shinyApp(ui, server)