后台数据shiny翻译v1.o

持久性数据存储在闪亮的应用程序

 

发表于 2015 年 7 月 1 日

这篇文章也刊登RStudio 的闪亮篇

 

闪亮的应用程序经常需要保存数据,加载到一个不同的会话,或只是用于记录一些信息。然而,常见的存储数据从 R 方法可能不搭配闪亮。像write.csv()和saveRDS()保存数据本地,但考虑shinyapps.io是如何工作的功能。

 

Shinyapps.io 是一个受欢迎的服务器申办闪亮的应用程序。它被设计来分发您闪亮的应用程序跨不同的服务器,这意味着,如果在一个会话期间在某些服务器上保存文件,然后再加载应用程序将可能直接你到不同的服务器在哪里先前保存的文件不存在。

 

在其他情况下,您可以使用数据太大,与 R 将本地存储,以有效的方式。

 

本指南将解释为存储持久数据远程与闪亮的 app 的七种方法。您将学习如何存储:

 

可以作为一个文件在某种形式的一种文件系统(本地文件系统, Dropbox,亚马逊 S3存储任意数据)

矩形结构化数据可以被存储为一个表在一个关系数据库或表存储服务(SQLite, MySQL,谷歌床单)

可以作为集合(MongoDB NoSQL 数据库中存储半结构化的数据)

本文解释了每种方法,背后的理论,增强工作的事例,会让它清楚,便于您在您自己的应用程序中使用这些方法与理论。

 

作为这篇文章的补充,你可以看到一个闪亮的应用程序的实时演示使用每个七的存储方法,来保存和加载数据(在 GitHub 上的源代码)。这篇文章详述杰夫艾伦条关于在会话之间共享数据.

 

表的内容

 

没有数据存储的基本闪亮程序

本地与远程存储

持久性数据存储方法

在文件中存储任意数据

本地文件系统 (本地)

Dropbox (远程)

亚马逊 S3 (远程)

在表中存储结构化的数据

SQLite (本地)

MySQL (本地或远程)

谷歌床单 (远程)

在 NoSQL 数据库中存储半结构化的数据

MongoDB (本地或远程)

结论

没有数据存储的基本闪亮程序

 

演示如何使用每个存储类型存储数据,我们将开始与一个简单的表单提交闪亮的应用程序,

 

从用户那里收集了一些信息

存储他们的反应,和

显示所有以前的响应

最初该应用程序将只保存其 R 会话内响应。我们后来将了解到如何修改应用程序来使用每个不同的存储类型。

 

下面是代码的基本应用程序,我们将使用作为我们的起点 — — 将它复制到一个名为app.R.(你不知道的情况下: 闪亮的应用程序不在被划分成单独的ui.R和server.R文件,他们可以完全定义在一个文件作为此闪亮篇文章解释了)

 

library(shiny)

 

# Define the fields we want to save from the form

fields <- c("name", "used_shiny", "r_num_years")

 

# Shiny app with 3 fields that the user can submit data for

shinyApp(

  ui = fluidPage(

    DT::dataTableOutput("responses", width = 300), tags$hr(),

    textInput("name", "Name", ""),

    checkboxInput("used_shiny", "I've built a Shiny app in R before", FALSE),

    sliderInput("r_num_years", "Number of years using R",

                0, 25, 2, ticks = FALSE),

    actionButton("submit", "Submit")

  ),

  server = function(input, output, session) {

   

    # Whenever a field is filled, aggregate all form data

    formData <- reactive({

      data <- sapply(fields, function(x) input[[x]])

      data

    })

   

    # When the Submit button is clicked, save the form data

    observeEvent(input$submit, {

      saveData(formData())

    })

   

    # Show the previous responses

    # (update with current response when Submit is clicked)

    output$responses <- DT::renderDataTable({

      input$submit

      loadData()

    })    

  }

)

上面的代码是取自指导如何模仿谷歌具有闪亮的窗体.

 

上述应用程序是非常简单 — — 那里是一个表,显示所有响应,三个输入字段和一个提交按钮,将输入字段中获取数据并将其保存。您可能会发现未定义,但在应用程序中使用的两个函数: saveData(data)和loadData()。这两个函数是影响数据是如何存储的所检索的唯一的代码,我们将为每个数据存储类型重定义它们。为了使该应用程序,现在,在这里工作的保存和加载的普通实现功能那只是商店的反应当前的 R 会话中。

 

saveData <- function(data) {

  data <- as.data.frame(t(data))

  if (exists("responses")) {

    responses <<- rbind(responses, data)

  } else {

    responses <<- data

  }

}

 

loadData <- function() {

  if (exists("responses")) {

    responses

  }

}

在继续前进一步,确保这个基本的应用程序适合你和你明白每一行在它 — — 它并不难,但要花两分钟去通过它。这个应用程序的代码也可以作为依据和您可以运行它复制到您的 RStudio IDE 的所有代码或者通过运行shiny::runGist("c4db11d81f3c46a7c4a5").

 

本地与远程存储

 

到不同的存储方法之前,一个重要的区别,理解是本地存储vs远程存储.

 

本地存储意味着保存在同一台机器上的文件,运行闪亮的应用程序。功能像write.csv(), write.table()和saveRDS()实现本地存储,因为他们将文件保存在运行应用程序本地存储的机器是一般快比远程存储,但是如果应该只使用它您始终可以访问到保存文件的机器。

 

远程存储是指将数据保存在另一台服务器,通常是可靠的托管的服务器,如 Dropbox、 亚马逊或承载的数据库。一个大使用托管远程存储解决方案的优点是他们要可靠得多,一般可以将更多信任,以保持您的数据,还活着且未被破坏。

 

通过下面的不同存储类型选项的时候,请记住如果您闪亮的应用程序宿主在 shinyapps.io 上,你将不得不暂时使用远程存储方法。RStudio 计划很快在 shinyapps.io 上实现持久性存储。同时,使用本地存储只是一个选项如果你主人自己的闪亮的服务器。如果您想要承载您自己的服务器,这里有一个指南,详细介绍了如何设置你自己闪亮的服务器。

 

持久性数据存储方法

 

使用上述的闪亮应用程序,我们可以存储和检索响应在许多不同的方式。在这里我们将去通过七种方法实现数据持久性,可以容易地集成到闪亮的应用程序。对于每个方法,我们将解释方法并提供一个版本的saveData()和loadData()实现该方法。要为存储类型的示例应用程序中使用的方法,运行应用程序的适当版本的saveData()和loadData().

 

作为一个提醒,你可以看到被一道使用,在此生活的闪亮应用程序的确切代码使用的所有七个不同的存储类型.

 

这里是我们将学习使用不同的存储类型的摘要。

 

方法   数据类型   本地存储   远程存储   R 包

本地文件系统   任意数据   是的      -

Dropbox       任意数据              是的       rdrop2

亚马逊 S3   任意数据      是的   aws.s3

SQLite       结构化的数据       是的              RSQLite

MySQL       结构化的数据       是的       是的       RMySQL

谷歌床单   结构化的数据      是的   googlesheets

MongoDB       半结构化的数据       是的       是的       mongolite

在文件中存储任意数据

 

这是最灵活的选项来存储数据,因为文件使您可以存储任何类型的数据,无论是单个值、 大data.frame或任意数据。有使用文件来存储数据的两种常见情况:

 

你有一个文件,获取多次覆盖和使用的所有会话 (像杰夫艾伦的文章中的示例),或

你保存一个新文件,每次有新的数据

在我们的例子中我们将使用后者因为我们想要保存每个响应作为它自己的文件。我们可以使用前一种选择,但然后我们将介绍潜在的竞态条件将复杂化应用程序。当两个用户在同一时间,提交的响应,但因为该文件不能同时处理多个编辑,一位用户将覆盖其他用户的响应,就会发生争用条件。

 

保存多个文件,时,重要的是保存每个文件具有不同的文件名称,以避免覆盖文件。有很多方式做到这一点。例如,你可以简单地使用当前时间戳和md5 哈希值的数据被保存为文件的名称以确保没有两种形式提交有相同的文件名。

 

任意数据可以存储在本地文件系统上或远程服务,如 Dropbox 或亚马逊 S3 的文件。

 

1.本地文件系统 (本地)

 

最琐碎的方式将数据保存从闪亮是简单地将每个响应另存为自己当前服务器上的文件。若要加载的数据,我们只需加载输出目录中的所有文件。在我们特定的示例中,我们也要将所有的数据文件连接在一起一data.frame.

 

安装程序:所需的唯一设置是创建输出目录 (在这种情况下的响应),并确保闪亮的应用程序具有文件权限读写在该目录中。

 

代码:

 

outputDir <- "responses"

 

saveData <- function(data) {

  data <- t(data)

  # Create a unique file name

  fileName <- sprintf("%s_%s.csv", as.integer(Sys.time()), digest::digest(data))

  # Write the file to the local system

  write.csv(

    x = data,

    file = file.path(outputDir, fileName),

    row.names = FALSE, quote = TRUE

  )

}

 

loadData <- function() {

  # Read all the files into a list

  files <- list.files(outputDir, full.names = TRUE)

  data <- lapply(files, read.csv, stringsAsFactors = FALSE)

  # Concatenate all data together into one data.frame

  data <- do.call(rbind, data)

  data

}

2.收存箱 (远程)

 

如果你想要存储与一个远程的托管解决方案,而不是本地文件系统的任意文件,您可以存储上Dropbox的文件。Dropbox 是一个文件存储服务使您能够承载任何文件,到某些最大使用率。免费帐户提供了足够的存储空间,并且应该是足够存储大多数数据从闪亮的应用程序。

 

这种方法是类似于以前的方法,使用本地文件系统。唯一的区别是,现在,文件会被保存到和从 Dropbox 加载。你可以使用rdrop2包与 Dropbox 从 R.注意, rdrop2可以只有现有文件移动到 Dropbox,所以我们还需要将它存储在 Dropbox 上之前,请创建一个本地文件进行交互。

 

安装程序:您需要有一个 Dropbox 账户并创建一个文件夹以存储的响应。您还需要将身份验证添加到rdrop2与建议包自述文件中的任何方法。我选择的身份验证方法是验证手动一次并将生成的.httr-oauth文件获取创建复制到闪亮 app 文件夹。

 

代码:

 

library(rdrop2)

outputDir <- "responses"

 

saveData <- function(data) {

  data <- t(data)

  # Create a unique file name

  fileName <- sprintf("%s_%s.csv", as.integer(Sys.time()), digest::digest(data))

  # Write the data to a temporary file locally

  filePath <- file.path(tempdir(), fileName)

  write.csv(data, filePath, row.names = FALSE, quote = TRUE)

  # Upload the file to Dropbox

  drop_upload(filePath, dest = outputDir)

}

 

loadData <- function() {

  # Read all the files into a list

  filesInfo <- drop_dir(outputDir)

  filePaths <- filesInfo$path

  data <- lapply(filePaths, drop_read_csv, stringsAsFactors = FALSE)

  # Concatenate all data together into one data.frame

  data <- do.call(rbind, data)

  data

}

3.亚马逊 S3 (远程)

 

简而言之,Dropbox 申办文件网上流行的另一种是亚马逊 S3或S3 。就像有了 Dropbox,都可以装载任何类型的文件在 s3 中,但而不是放置在目录内的文件,在 S3 中你将文件放在桶里面。可以使用aws.s3软件包进行交互与 S3 从 R.注意包还没有对克伦所以你要看看其自述文件,了解安装说明。

 

安装程序:你需要有一个亚马逊网络服务帐户,创建一个 s3 来存储响应。作为包文档解释了,你将需要设置一些环境变量,以调用 API。

 

代码:

 

library(aws.s3)

 

s3BucketName <- "my-unique-s3-bucket-name"

Sys.setenv("AWS_ACCESS_KEY_ID" = "key",

           "AWS_SECRET_ACCESS_KEY" = "secret",

           "AWS_DEFAULT_REGION" = "region")

 

saveData <- function(data) {

  # Create a plain-text representation of the data

  data <- paste0(

    paste(names(data), collapse = ","), "\n",

    paste(unname(data), collapse = ",")

  )

 

  file_name <- paste0(

    paste(

      get_time_human(),

      digest(data, algo = "md5"),

      sep = "_"

    ),

    ".csv"

  )

 

  # Upload the file to S3

  put_object(file = charToRaw(data), object = file_name, bucket = s3_bucket_name)

}

 

loadData <- function() {

  # Get a list of all files

  file_names <- get_bucket_df(s3BucketName)[["Key"]]

  # Read all files into a list

  data <- lapply(file_names, function(x) {

    object <- get_object(x, s3BucketName)

    object_data <- readBin(object, "character")

    read.csv(text = object_data, stringsAsFactors = FALSE)

  })

  # Concatenate all data together into one data.frame

  data <- do.call(rbind, data)

  data 

}

在表中存储结构化的数据

 

如果您想要保存的数据是结构化和矩形,将其存储在表中将一个不错的选择。松散定义的结构化数据意味着,每个观察值具有相同的固定的字段,矩形数据意味着所有意见包含相同数量的字段放入一个好的二维矩阵。Data.frame是很好的例子,这类数据,因此 data.frames 是理想的候选人要存储在关系数据库的表中。

 

结构化的数据必须有一些定义的数据字段的架构。在data.frame中,列的名称和数目可以被认为是架构。在具有标题行的表,可以为架构思潮的标题行。

 

结构化的数据可以存储在关系数据库中 (例如 SQLite 或 MySQL) 或任何其他表托管服务如谷歌表在表中。如果你有经验的数据库接口在其他语言中,你应该注意到,R 目前没有支持预准备语句,所以任何 SQL 语句必须手动构造。使用关系数据库的优点之一是,与大多数数据库是安全有多个用户同时使用数据库,而不会遇到由于事务支持的争用条件.

 

4 (当地SQLite 段)

 

SQLite 是一个非常简单、 重量轻的关系数据库,是很容易设置。SQLite 是无服务器,这意味着它正在运行的有光泽的应用程序的同一台计算机上本地存储的数据库。您可以使用RSQLite包与从 R.SQLite 交互要连接到在 R 的 SQLite 数据库,您需要提供的唯一信息是数据库文件的位置。

 

在 SQLite 数据库中存储数据,我们遍历所有我们想要添加和使用SQL INSERT语句将数据添加到数据库的值。至关重要的是数据库的架构匹配正好在闪亮的数据列的名称,否则 SQL 语句将会失败。若要加载以前的所有数据,我们使用纯SQL SELECT *语句来从数据库表中得到的所有数据。

 

安装程序:首先,您必须在您的服务器上安装的 SQLite。安装是非常容易的;例如,在 Ubuntu 机器上你可以安装 SQLite sudo apt-get install sqlite3 libsqlite3-dev。如果您使用 shinyapps.io,SQLite 已经安装在 shinyapps.io 服务器上,这将是一个方便的特性,在未来版本的 shinyapps.io,其中将包括持久性的本地存储区中。

 

您还需要创建一个数据库和一个表,将存储所有的响应。当创建表,您需要设置表的架构以匹配您的数据的列。例如,如果您想要保存数据的"名称"列和"电子邮件"然后可以与CREATE TABLE responses(name TEXT, email TEXT);创建 SQL 表。请确保闪亮的应用程序上的数据库文件和它的父目录具有写权限。

 

代码:

 

library(RSQLite)

sqlitePath <- "/path/to/sqlite/database"

table <- "responses"

 

saveData <- function(data) {

  # Connect to the database

  db <- dbConnect(SQLite(), sqlitePath)

  # Construct the update query by looping over the data fields

  query <- sprintf(

    "INSERT INTO %s (%s) VALUES ('%s')",

    table, 

    paste(names(data), collapse = ", "),

    paste(data, collapse = "', '")

  )

  # Submit the update query and disconnect

  dbGetQuery(db, query)

  dbDisconnect(db)

}

 

loadData <- function() {

  # Connect to the database

  db <- dbConnect(SQLite(), sqlitePath)

  # Construct the fetching query

  query <- sprintf("SELECT * FROM %s", table)

  # Submit the fetch query and disconnect

  data <- dbGetQuery(db, query)

  dbDisconnect(db)

  data

}

5.MySQL (本地或远程)

 

MySQL 是一个非常流行的关系数据库,是类似于 SQLite 却更强大。MySQL 数据库可以是托管本地 (同一台计算机上的闪亮的应用程序) 或在线使用的托管服务。

 

这种方法是非常类似于前面的 SQLite 方法,主要区别在于所在的数据库。您可以使用RMySQL包与 MySQL 从 R.交互由于 MySQL 数据库可以驻留在远程服务器上,连接到服务器的命令涉及到更多的参数,但保存/加载代码的其余部分是的 SQLite 方法完全相同。要连接到一个 MySQL 数据库,您需要提供以下参数: 主机、 端口、 数据库名称、 用户、 密码。

 

安装程序:您需要创建一个 MySQL 数据库 (本地或使用承载 MySQL 数据库的 web 服务) 和一个表,将存储的响应。Sqlite,设置您需要确保表架构正确设置了您预期的数据。

 

代码:

 

library(RMySQL)

 

options(mysql = list(

  "host" = "127.0.0.1",

  "port" = 3306,

  "user" = "myuser",

  "password" = "mypassword"

))

databaseName <- "myshinydatabase"

table <- "responses"

 

saveData <- function(data) {

  # Connect to the database

  db <- dbConnect(MySQL(), dbname = databaseName, host = options()$mysql$host,

      port = options()$mysql$port, user = options()$mysql$user,

      password = options()$mysql$password)

  # Construct the update query by looping over the data fields

  query <- sprintf(

    "INSERT INTO %s (%s) VALUES ('%s')",

    table, 

    paste(names(data), collapse = ", "),

    paste(data, collapse = "', '")

  )

  # Submit the update query and disconnect

  dbGetQuery(db, query)

  dbDisconnect(db)

}

 

loadData <- function() {

  # Connect to the database

  db <- dbConnect(MySQL(), dbname = databaseName, host = options()$mysql$host,

      port = options()$mysql$port, user = options()$mysql$user,

      password = options()$mysql$password)

  # Construct the fetching query

  query <- sprintf("SELECT * FROM %s", table)

  # Submit the fetch query and disconnect

  data <- dbGetQuery(db, query)

  dbDisconnect(db)

  data

}

6.谷歌床单 (远程)

 

如果你不想处理拘谨和僵化的数据库,用于存储表格数据的另一个选项是在谷歌工作表中。谷歌床单的一个很大的优势是它们很容易访问从任何地方;但与不同的数据库,与谷歌床单数据可以覆盖多个并发用户。

 

您可以使用googlesheets包与谷歌床单从 R.交互若要连接到特定的表,您将需要工作表的标题或键 (最好是关键,因为它是唯一)。它是非常容易地存储或检索数据从谷歌的工作表,如下面的代码显示。

 

安装程序:所有你需要做是创建一个谷歌表和设置字段的名称的顶行。你可以通过 web 浏览器或使用googlesheets软件包。你还需要有一个谷歌帐户。googlesheets包为rdrop2,使用类似的方法,对身份验证,因此您也需要进行身份验证以类似的方式,如将有效.httr-oauth文件复制到你闪亮的目录。

 

代码:

 

library(googlesheets)

 

table <- "responses"

 

saveData <- function(data) {

  # Grab the Google Sheet

  sheet <- gs_title(table)

  # Add the data as a new row

  gs_add_row(sheet, input = data)

}

 

loadData <- function() {

  # Grab the Google Sheet

  sheet <- gs_title(table)

  # Read the data

  gs_read_csv(sheet)

}

在 NoSQL 数据库中存储半结构化的数据

 

如果你有数据结构不完全但也不是完全自由的一个好的中间立场可以使用 NoSQL 数据库。NoSQL 数据库可以也被称为无模式数据库因为他们不使用正式的架构。NoSQL 数据库仍然提供的一些优点传统的关系数据库中,但是是更灵活的因为每个条目可以使用不同的字段。如果您闪亮的应用程序需要将具有多个字段的数据存储,但没有统一的架构,为所有要使用的数据,然后使用 NoSQL 数据库可以是一个不错的选择。

 

有许多 NoSQL 数据库可用,但在这里我们只会显示如何使用 mongoDB。

 

7.MongoDB (本地或远程)

 

MongoDB 是一个最受欢迎的 NoSQL 数据库,并就像 MySQL 可以主办本地或远程方式。有很多提供 mongoDB 主办,包括MongoLab给你免费 mongoDB 数据库的 web 服务。在 mongoDB 中,(在本例中,响应) 条目存储在一个集合(相当于 S3 存储桶或 SQL 表) 中。

 

您可以使用mongolite包与从 R.mongoDB 交互与关系数据库的方法,所有我们需要做为了保存/加载数据是连接到数据库并提交相应的更新或选择查询。要连接到的数据库,您需要提供以下: db,主机、 用户名、 密码。保存数据时, mongolite需要要在 data.frame 格式的数据。

 

安装程序:所有你需要做的是创建 mongoDB 数据库 — — 要么本地或使用 web 服务,如 MongoLab。由于没有架构,它不是强制性创建集合之前填充它。

 

代码:

 

library(mongolite)

 

options(mongodb = list(

  "host" = "ds012345.mongolab.com:61631",

  "username" = "myuser",

  "password" = "mypassword"

))

databaseName <- "myshinydatabase"

collectionName <- "responses"

 

saveData <- function(data) {

  # Connect to the database

  db <- mongo(collection = collectionName,

              url = sprintf(

                "mongodb://%s:%s@%s/%s",

                options()$mongodb$username,

                options()$mongodb$password,

                options()$mongodb$host,

                databaseName))

  # Insert the data into the mongo collection as a data.frame

  data <- as.data.frame(t(data))

  db$insert(data)

}

 

loadData <- function() {

  # Connect to the database

  db <- mongo(collection = collectionName,

              url = sprintf(

                "mongodb://%s:%s@%s/%s",

                options()$mongodb$username,

                options()$mongodb$password,

                options()$mongodb$host,

                databaseName))

  # Read all the entries

  data <- db$find()

  data

}

结论

 

持久性存储可以让您更用你闪亮的应用程序做的事情。您甚至可以使用持久性存储访问和写入远程数据集,否则会太大了,在 R.操纵

 

下表可以作为一个提醒的不同存储类型以及何时使用它们。请记住,使用本地存储的任何方法可以只用于闪亮在服务器上,而使用远程存储的任何方法也可以在 shinyapps.io 上。

 

方法   数据类型   本地存储   远程存储   R 包

本地文件系统   任意数据   是的      -

Dropbox       任意数据              是的       rdrop2

亚马逊 S3   任意数据      是的   aws.s3

SQLite       结构化的数据       是的              RSQLite

MySQL       结构化的数据       是的       是的       RMySQL

谷歌床单   结构化的数据      是的   googlesheets

MongoDB       半结构化的数据       是的       是的       mongolite

标签: 专业,rstats,r,r-博客,发亮,教程,流行

posted on 2017-09-18 20:05  宋宋66  阅读(177)  评论(0)    收藏  举报

导航