概述

我对如何开发和部署"Shiny-SparkR"的应用一直很感兴趣,本文将展示如何使用 SparkR 来驱动 Shiny 应用。

什么是SparkR

SparkR是一个为R提供了轻量级的Spark前端的R包。 SparkR提供了一个分布式的data frame数据结构,解决了 R中的data frame只能在单机中使用的瓶颈,它和R中的data frame 一样支持许多操作,比如select,filter,aggregate等等。(类似dplyr包中的功能)这很好的解决了R的大数据级瓶颈问题。 SparkR也支持分布式的机器学习算法,比如使用MLib机器学习库。

什么是Shiny

Shiny 是一个开源的 R 包,它为使用 R 构建 Web 应用提供了一个优雅有力的 Web 框架。Shiny 帮助你在不需要前端知识的条件下将数据分析转变为可交互的 Web 应用。

用例

你可能会问自己,“为什么我需要使用SparkR运行我的程序?”。这是一个合乎情理的问题和回答,我们需要理解不同类型的大数据问题。

大数据问题的分类

最近,在 Reddit 的 AMA频道 上, Hadley Wickham(RStudio首席科学家)描绘了一幅清晰的“大数据”定义。他的见解将帮助我们为SparkR和Shiny定义用例。

我认为大数据问题应分类三个主要类:

  • 大数据小分析:数据科学家针对某一个特定的业务或研究问题从一个大的原始数据集开始做数据切片和数据抽样。
    在大多数项目中,抽样结果都是小数据集,而这些项目中并不需要用到 SparkR 来驱动 Shiny应用。

  • 分片聚合分析:数据科学家需要在多台机器上分布式地并行计算。Wickham 认为这是一个琐碎的并行化问题。一个例子就是当大规模计算时,你需要在成千上万的机器上为每一个机器都拟合一个模型。在这种情况下 SparkR 是一个不错的选择,但也可以用 R 的 foreach等包来解决这个问题。

  • 大规模的数据分析:数据科学家需要大数据,可能是因为他们在处理一个复杂的模型拟合。这类问题的一个例子就是推荐系统。因为他们需要捕捉到用户稀疏的交互,推荐系统确实从大量数据中获益。当开发 Shiny 应用时,SparkR 可以完美解决这类问题。

内存方面的考虑

此外,当想使用这样的应用程序时,考虑内存的可用性和大小也是很重要的。这可以用两种不同的方式:

  • 如果您正在运行的应用程序服务器上有足够的内存来满足你的大数据需求,你可能根本就不需要 SparkR 了。现在有像 Amazon AWS 一样的云提供商提供上T的计算内存。

  • 如果你的大数据不能装在一台机器上,您可能需要分配在几个机器。SparkR 适合这一问题,因为它提供了分布式算法,可以压缩不同节点数据并将结果返回给主节点。

一个简单的例子

在我们开始理解每一块这样的应用程序将如何操作,先让我们下载这个简单 Shiny-SparkR 并运行应用程序。项目地址目录下的“shiny-sparkr-demo-1”可以获取示例。

准备

  • 安装Spark 1.5 及以上版本。

  • 安装 Java 1.7 及以上版本,并配置环境变量。

启动应用程序

一旦你下载了应用文件夹,打开项目RStudio并打开“server.R”文件。

  1. 改变SPARK_HOME环境变量的路径,使之指向安装Spark的位置。

  1. 运行应用程序. 通过使用这个命令 shiny::runApp()运行应用程序。在分析的结果显示出来之前,SparkR初始化需要一些时间。

  1. 这是“server.R”的代码。

# 首先一次安装shiny库
library(shiny)

# 设置系统环境变量
Sys.setenv(SPARK_HOME = "/home/emaasit/Desktop/Apache/spark-1.5.2")
.libPaths(c(file.path(Sys.getenv("SPARK_HOME"), "R", "lib"), .libPaths()))

# 加载Sparkr库
library(SparkR)

# 创建一个 Spark Context 和 SQL Context
sc <- sparkR.init(master = "local")
sqlContext <- sparkRSQL.init(sc)

# 为“iris”数据集创建一个 sparkR DataFrame
iris_DF <- createDataFrame(sqlContext, iris)
cache(iris_DF)

# 定义需要预测 sepal length 的后端逻辑
shinyServer(function(input, output) {

  # 机器学习
  
  model_fit <- glm(Sepal_Length ~ Species + Petal_Width + Petal_Length, data = iris_DF, family = "gaussian")
  
  output$summary_model <- renderPrint({summary(model_fit)})
  
  output$predict_new_value <- renderText({
    
    input$predictSepalLength
    
    isolate({
      Species <- as.character(input$species) 
      Petal_Width <- as.double(input$petalWidth)
      Petal_Length <- as.double(input$petalLength)
      
      
      
      new_data_frame <- data.frame(Species = Species, 
                                 Petal_Width = Petal_Width,
                                 Petal_Length = Petal_Length)
      
      newDataFrame <- createDataFrame(sqlContext, new_data_frame)
      
      predicted_value <- predict(model_fit, newData = newDataFrame)
      
      unlist(head(select(predicted_value, "prediction")))
    })
  })
  
  
})

结果

第一步:

当您运行这个应用程序, 显示的用户界面中不会有文字渲染或者模型总结数据。

第二步:

与此同时,在你的电脑后台的节点(s)上,java使用Spark-submit启动文件,然后SparkR库加载SparkR初始化。

第三步:

然后SparkR命令在"server.R"的代码中执行,最后在 Shiny的应用程序中显示的输出。

访问localhost的4040端口,您可以使用 Spark UI 检查任务调度的进度。

第四步:

当你在应用中修改了输入值并点击了"Predict Sepal Length"按钮,这个应用会将你输入的值作为 Spark Context,用来执行预测函数并且显示预测值。相比于初始化 Shiny 应用,这个操作只需要很短的时间。

展望

这个示例的目的是讲解如何学习 SparkR 和 Shiny 的用例;想看看会发生什么还需要你最终在电脑上部署并运行应用一下。

如果你建立了这样的应用程序,请在评论中分享你的想法和经历下面的部分。

本文已获得原作者:Daniel Emaasit 授权,并由 HarryZhu 翻译。
英文原文地址:http://blog.sparkiq-labs.com/2015/11/22/using-apache-sparkr-to-power-shiny-applications-part-i/

作为分享主义者(sharism),本人所有互联网发布的图文均遵从CC版权,转载请保留作者信息并注明作者 Harry Zhu 的 FinanceR 专栏:https://segmentfault.com/blog/harryprince,如果涉及源代码请注明GitHub地址:https://github.com/harryprince。微信号: harryzhustudio
商业使用请联系作者。


HarryZhu
2.2k 声望2.2k 粉丝