2016-12-15 8 views
0

Я создаю блестящее приложение, часть которого вычисляет модель линейной регрессии на основе данных, загруженных и измененных пользователем. Я делаю все шаг за шагом, поэтому здесь я покажу вам только код тестового приложения, касающийся основной проблемы. Идея такова:Изменение и объединение реактивной части данных, загруженной пользователем в блестящем приложении

  1. добавление пользователя данные из файла .csv с помощью fileInput в блестящих
  2. данных показывает вверх, а затем, после проверки его, пользователь может изменить переменные по своему выбору
  3. Каждого отобранным и модифицирован переменный показывает со старым переменными как новым реактивным DataTable - мне удалось получить через него с помощью этого: Add values to a reactive table in shiny

Теперь, все это прекрасно работает на код ниже, если указан начальный набор данных:

test_df <- data.frame(a = seq(1000, 21000, 1000), b = seq(1:21), c = seq(100, 300, 10)) 

library(shiny) 

runApp(list(
    ui=pageWithSidebar(headerPanel("Adding entries to table"), 
       sidebarPanel(uiOutput("select1"), 
           selectInput("select2", "Choose modification", 
              choices = c("log", "different"), 
              selected = NULL, multiple = F), 
           actionButton("update", "Update Table")), 
       mainPanel(tableOutput("table1"))), 

server=function(input, output, session) { 

values <- reactiveValues() 

### specifing the dataset ### 
values$df <- data.frame(test_df) 
nr <<- nrow(test_df) 

### this will contain the modified values ### 
values$d <- data.frame(1:nr) 

### selecting a variable to modify ### 
output$select1 <- renderUI({ 
    nc <- ncol(values$df) 
    nam <- colnames(values$df) 
    selectInput("var", label = "Select var:", 
       choices = c(nam), multiple = F, 
       selected = nam[1]) 
}) 

### calculations needed for modifactions ### 
newEntry <- observeEvent(input$update, { 

    if(input$select2 == "log") { 
    newCol <- isolate(
     c(log(values$df[input$var])) 
    ) 
    newCol <- as.data.frame(newCol) 
    colnames(newCol) <- paste0("Log of ", input$var) 
    } 

    else if(input$select2 == "different") { 
    newCol <- isolate(
     c(1-exp(-(values$df[input$var]/100))) 
    ) 
    newCol <- as.data.frame(newCol) 
    colnames(newCol) <- paste0(input$var, "Diff of", input$dr1) 
    } 
    ### adding new modified columns to the dataframe ### 
    isolate(
    values$d <- dplyr::bind_cols(values$d, newCol) 
) 

}) 

output$table1 <- renderTable({ 
    d1 <- values$d 
    nc <- ncol(d1) 

    ### printing the whole dataframe (initial+modified) - skipping ### 
    ### the first column of modified values, as it doesn't contain our data ### 
    if(input$update == 0) { 
    print(data.frame(test_df)) 
    } else { 
    data.frame(values$df, d1[2:nc]) 
    } 
}) 

})) 

Однако, когда я хочу, чтобы включить первый шаг, который означает загрузку набора данных ПОСЛЕ запуска приложения, то приложение не запускается, так как теперь я имею в виду реактивный контент, которого, вероятно, не существует. Вот обновленный код, с характеристикой загрузки данных из собственного источника:

library(shiny) 

runApp(list(
ui=pageWithSidebar(headerPanel("Adding entries to table"), 
       sidebarPanel(fileInput("file1", "Choose file to upload", accept = c("text/csv", "text/comma-separated-values", "text/tab-separated-values", "text/plain", ".csv",".tsv")), 
           checkboxInput("header", "Header", TRUE), 
           radioButtons("sep", "Separator",c(Comma=",",Semicolon=";",Tab="\t"),","), 
           radioButtons("dec", "Decimal",c(Comma=",",Dot="."),","), 
           actionButton("Load", "Load the File"), 
           uiOutput("select1"), 
           selectInput("select2", "Choose modification", 
              choices = c("log", "different"), 
              selected = NULL, multiple = F), 
           actionButton("update", "Update Table")), 
       mainPanel(tableOutput("table1"))), 

server=function(input, output, session) { 

values <- reactiveValues() 

### uploading data from external source ### 
data1 <- reactive({ 
    if(input$Load == 0){return()} 
    inFile <- input$file1 
    if (is.null(inFile)){return(NULL)} 

    isolate({ 
    input$Load 
    my_data <- read.csv(inFile$datapath, header = input$header, sep = input$sep, stringsAsFactors = FALSE, dec = input$dec) 
    }) 
    my_data 
}) 

### specifing the dataset ### 
values$df <- data.frame(data1()) 
nr <<- nrow(data1()) 

### this will contain the modified values ### 
values$d <- data.frame(1:nr) 

### selecting a variable to modify ### 
output$select1 <- renderUI({ 
    nc <- ncol(values$df) 
    nam <- colnames(values$df) 
    selectInput("var", label = "Select var:", 
       choices = c(nam), multiple = F, 
       selected = nam[1]) 
}) 

### calculations needed for modifactions ### 
newEntry <- observeEvent(input$update, { 

    if(input$select2 == "log") { 
    newCol <- isolate(
     c(log(values$df[input$var])) 
    ) 
    newCol <- as.data.frame(newCol) 
    colnames(newCol) <- paste0("Log of ", input$var) 
    } 

    else if(input$select2 == "different") { 
    newCol <- isolate(
     c(1-exp(-(values$df[input$var]/100))) 
    ) 
    newCol <- as.data.frame(newCol) 
    colnames(newCol) <- paste0(input$var, "Diff of", input$dr1) 
    } 
    ### adding new modified columns to the dataframe ### 
    isolate(
    values$d <- dplyr::bind_cols(values$d, newCol) 
) 

}) 

output$table1 <- renderTable({ 
    d1 <- values$d 
    nc <- ncol(d1) 

    ### printing the whole dataframe (initial+modified) - skipping the first ### 
    ### column of modified values, as it doesn't contain our data ### 
    if(input$update == 0) { 
    print(data.frame(test_df)) 
    } else { 
    data.frame(values$df, d1[2:nc]) 
    } 
}) 

})) 

Я получаю ошибку:

Ошибка в .getReactiveEnvironment() $ currentContext: Операция не допускается> без активный активный контекст. (Вы пытались сделать что-то, что только можно> сделать внутри реактивным выражения или наблюдателя.)

Конечно, я кое-что о реакционной глянцеватых не хватает, но я тщательно читал много разных статей, вопросы и т. д., и не может найти ответ на этот вопрос. Это не проблема с загрузкой самого файла, потому что этот блок кода отлично работает в другом приложении, когда я пишу реактивный набор данных к нормальной переменной, прежде чем ссылаться на его содержимое. Но как я могу это сделать здесь, когда записываю данные в values$...? Или, может быть, есть другое решение для работы с реактивными данными из внешнего источника, таким образом? Надеюсь, я все понял.

+0

Помогает ли вам вставить 'req (input $ file1)' в начале 'data1'' реактивный'? –

+0

@JohnPaul Нет, это не так, приложение отключается с той же ошибкой. –

+0

Попытайтесь поместить свои 'значения $ xxx' внутри наблюдателя, когда они заметят в реактивном контексте, например' наблюдать ({значения $ df <- data1()}) '. Здесь 'data1()' является реактивным, поэтому ваш код не работает. –

ответ

0

Спасибо @ StéphaneLaurent за помощь! Все еще были проблемы с глобальной переменной nr, но следующие изменения заставляли ее работать.

Сначала я указываю тестовые данные, которые будут отображаться до того, как пользователь загрузит любые данные (поэтому приложение имеет некоторую базу для вычислений, а не null): test_df <- data.frame(a = seq(1000, 21000, 1000), b = seq(1:21), c = seq(100, 300, 10)).

Затем я использую его при определении реактивной dataframe, в случае, если нет никакого пользовательского ввода:

data1 <- reactive({ 
    if(input$Load == 0){return(test_df)} 
    inFile <- input$file1 
    if (is.null(inFile)){return(test_df)} 

    isolate({ 
    input$Load 
    my_data <- read.csv(inFile$datapath, header = input$header, sep = input$sep, stringsAsFactors = FALSE, dec = input$dec) 
    }) 
    my_data 
}) 

И, наконец, я использую observe функцию для моих переменных, которые зависят от некоторых других активных переменных:

observe({ 
    values$df <- data.frame(data1()) 
    nr <- nrow(data1()) 
    values$d <- data.frame(1:nr) 
}) 

Остальная часть кода не требует никаких дополнительных изменений, и приложение теперь работает отлично.