gpt4 book ai didi

r - 如何使用 shiny 保存文本文件中的更改?

转载 作者:行者123 更新时间:2023-12-05 05:21:23 25 4
gpt4 key购买 nike

我有一个用于注释文本文件的 Shiny 小应用。

  1. UI 提供fileInput 来选择.txt 文件。其中一个文件是应用程序启动时的默认文件。
  2. NextPrevious 按钮允许用户显示文件的内容,一次一个句子。
  3. 用户可以选择句子中的任何文本,然后单击添加标记 按钮为句子添加注释。操作按钮触发 javascript 函数 addMarkup()
  4. 句子被标记后显示。

我只是在这里发布 Shiny 的应用程序代码。该应用程序的完整代码可在 github repository 上获得

  library(shiny)
ui <- fluidPage(
tags$head(tags$script(src="textselection.js")),
titlePanel("Corpus Annotation Utility"),
sidebarLayout(
sidebarPanel(
fileInput('fileInput', 'Select Corpus', accept = c('text', 'text','.txt')),
actionButton("Previous", "Previous"),
actionButton("Next", "Next"),
actionButton("mark", "Add Markup")
),
mainPanel(
tags$h1("Sentence: "),
htmlOutput("sentence"),
tags$h1("Sentence marked up: "),
htmlOutput("sentenceMarkedUp")
)
)
)
server <- function(input, output) {
sourceData <- reactive({
corpusFile <- input$fileInput
if(is.null(corpusFile)){
return(readCorpus('data/news.txt'))
}
readCorpus(corpusFile$datapath)
})

corpus <- reactive({sourceData()})
values <- reactiveValues(current = 1)
observeEvent(input$Next,{
if(values$current >=1 & values$current < length(corpus())){
values$current <- values$current + 1
}
})
observeEvent(input$Previous,{
if(values$current > 1 & values$current <= length(corpus())){
values$current <- values$current - 1
}
})
output$sentence <- renderText(corpus()[values$current])
}
shinyApp(ui = ui, server = server)

readCorpus() 函数如下所示:

readCorpus <- function(pathToFile){
con <- file(pathToFile)
sentences <- readLines(con, encoding = "UTF-8")
close(con)
return(sentences)
}

我的问题是如何在注释后将句子保存到文件中?

screenshot of the app

更新:我经历了Persistent data storage in Shiny apps ,并希望我能够遵循有关持久存储的文档。但是我仍然不确定如何在标记后捕获句子。

最佳答案

这里有两个问题 - 持久化更改,然后保存输出。我使用一些 JS 和一些 R 代码解决了这个问题。我将在 Github 上执行拉取请求以提交更广泛的代码。然而,这是它的核心。

在用于选择内容的 Javascript 中,您可以使用 Shiny.onInputChange()更新 input 的元素向量。这样做,您可以创建一个 reactiveValues语料库的项目,然后使用您界面中的输入更新它。

在下面,您会注意到我从使用文本节点切换到仅使用内部 HTML。使用节点,和 firstChild ,正如您之前所做的那样,您最终会在第一个注释之后截断句子(因为它只选择 <mark> 之前的内容。这样做似乎效果更好。

window.onload = function(){
document.getElementById('mark').addEventListener('click', addMarkup);
}

function addMarkup(){
var sentence = document.getElementById("sentence").innerHTML,
selection="";
if(window.getSelection){
selection = window.getSelection().toString();
}
else if(document.selection && document.selection.type != "Control"){
selection = document.selection.createRange().text;
}
if(selection.length === 0){
return;
}
marked = "<mark>".concat(selection).concat("</mark>");
result = sentence.replace(selection, marked);
document.getElementById("sentence").innerHTML = result;
Shiny.onInputChange("textresult",result);
}

接下来,我尝试简化您的 server.R代码。您正在使用 react 上下文从另一个 react 上下文( sourceDatacorpus )中拉取,这似乎是不必要的。因此,我尝试对其进行一些重构。

library(shiny)
source("MyUtils.R")
ui <- fluidPage(
tags$head(tags$script(src="textselection.js")),
titlePanel("Corpus Annotation Utility"),
sidebarLayout(
sidebarPanel(
fileInput('fileInput', 'Select Corpus', accept = c('text', 'text','.txt')),
actionButton("Previous", "Previous"),
actionButton("Next", "Next"),
actionButton("mark", "Add Markup"),
downloadButton(outputId = "save",label = "Download")),
mainPanel(
tags$h1("Sentence: "),
htmlOutput("sentence"))
)
)

server <- function(input, output) {
corpus <- reactive({
corpusFile <- input$fileInput
if(is.null(corpusFile)) {
return(readCorpus('data/news.txt'))
} else {
return(readCorpus(corpusFile$datapath))
}
})

values <- reactiveValues(current = 1)
observe({
values$corpus <- corpus()
})
output$sentence <- renderText(values$corpus[values$current])

observeEvent(input$Next,{
if(values$current >=1 & values$current < length(corpus())) {
values$current <- values$current + 1
}
})
observeEvent(input$Previous,{
if(values$current > 1 & values$current <= length(corpus())) {
values$current <- values$current - 1
}
})
observeEvent(input$mark,{
values$corpus[values$current] <- input$textresult
})
output$save <- downloadHandler(filename = "marked_corpus.txt",
content = function(file) {

writeLines(text = values$corpus,
con = file,
sep = "\n")
})
}

现在,代码有一些变化。从文件加载基本相同。我对 isolate 的怀疑是对的- 将其替换为 observe完成了我想做的事情,而 isolate只会给你初始负载。无论如何,我们使用 observe将语料库值加载到 reactiveValues您创建的对象 - 这是为了给我们一个地方来传播对数据的更改。

我们保留前进和后退的剩余逻辑。但是,我们更改了呈现输出的方式,以便它查看 reactiveValues。目的。然后,我们创建一个更新 reactiveValues 的观察者对象与我们更新的 Javascript 的输入。发生这种情况时,数据将永久存储,您还可以在字符串中标记多个序列(尽管我没有对嵌套标记或删除标记进行任何操作)。最后,添加一个保存函数——结果字符串用<mark>保存出来。用于显示标记区域。

如果您加载以前标记过的文件,标记将再次出现。

关于r - 如何使用 shiny 保存文本文件中的更改?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42995447/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com