比较 SparkR 和 sparklyr
R 用户可以在适用于 Apache Spark 的两个 API 之间进行选择:SparkR 和 sparklyr。 本文将比较这些 API。 Databricks 建议选择其中一个 API 在 R 中开发 Spark 应用程序。将这两个 API 中的代码组合到单个脚本或者 Azure Databricks 笔记本或作业可能会导致代码更难以阅读和维护。
API 的来源
SparkR 由 Spark 社区和 Databricks 开发人员生成。 因此,SparkR 严格遵循 Spark Scala 类和数据帧 API。
sparklyr 最初出现于 RStudio,后来捐赠给了 Linux 基金会。 sparklyr 在编程风格方面与 tidyverse 紧密集成,并且与 dplyr 具有 API 互操作性。
SparkR 和 sparklyr 非常擅长处理 R 中的大数据。在过去几年,两者的功能集越来越接近,几乎不相上下。
API 差异
以下代码示例演示如何在 Azure Databricks 笔记本中使用 SparkR 和 sparklyr 将 CSV 文件从示例数据集读入 Spark。
# #############################################################################
# SparkR usage
# Note: To load SparkR into a Databricks notebook, run the following:
# library(SparkR)
# You can then remove "SparkR::" from the following function call.
# #############################################################################
# Use SparkR to read the airlines dataset from 2008.
airlinesDF <- SparkR::read.df(path = "/databricks-datasets/asa/airlines/2008.csv",
source = "csv",
inferSchema = "true",
header = "true")
# Print the loaded dataset's class name.
cat("Class of SparkR object: ", class(airlinesDF), "\n")
# Output:
#
# Class of SparkR object: SparkDataFrame
# #############################################################################
# sparklyr usage
# Note: To install, load, and connect with sparklyr in a Databricks notebook,
# run the following:
# install.packages("sparklyr")
# library(sparklyr)
# sc <- sparklyr::spark_connect(method = "databricks")
# If you run "library(sparklyr)", you can then remove "sparklyr::" from the
# preceding "spark_connect" and from the following function call.
# #############################################################################
# Use sparklyr to read the airlines dataset from 2007.
airlines_sdf <- sparklyr::spark_read_csv(sc = sc,
name = "airlines",
path = "/databricks-datasets/asa/airlines/2007.csv")
# Print the loaded dataset's class name.
cat("Class of sparklyr object: ", class(airlines_sdf))
# Output:
#
# Class of sparklyr object: tbl_spark tbl_sql tbl_lazy tbl
但是,如果你尝试在 SparkR 中对 SparkDataFrame
对象运行 sparklyr 函数,或者尝试在 sparklyr 中对 tbl_spark
对象运行 SparkR 函数,该函数将无法正常运行,如以下代码示例中所示。
# Try to call a sparklyr function on a SparkR SparkDataFrame object. It will not work.
sparklyr::sdf_pivot(airlinesDF, DepDelay ~ UniqueCarrier)
# Output:
#
# Error : Unable to retrieve a Spark DataFrame from object of class SparkDataFrame
## Now try to call s Spark R function on a sparklyr tbl_spark object. It also will not work.
SparkR::arrange(airlines_sdf, "DepDelay")
# Output:
#
# Error in (function (classes, fdef, mtable) :
# unable to find an inherited method for function 'arrange' for signature '"tbl_spark", "character"'
这是因为,sparklyr 将 dplyr 函数(例如 arrange
)转换为 SparkSQL 使用的 SQL 查询计划。 SparkR 并非如此,它提供适用于 SparkSQL 表和 Spark 数据帧的函数。 正因为存在这些行为,Databricks 不建议在同一脚本、笔记本或作业中结合使用 SparkR 和 sparklyr API。
API 互操作性
在不可避免地需要结合使用 SparkR 和 sparklyr API 的极少数情况下,可以使用 SparkSQL 作为一种衔接手段。 例如,在本文的第一个示例中,sparklyr 将 2007 年的航空公司数据集加载到名为 airlines
的表中。 可以使用 SparkR sql
函数查询此表,例如:
top10delaysDF <- SparkR::sql("SELECT
UniqueCarrier,
DepDelay,
Origin
FROM
airlines
WHERE
DepDelay NOT LIKE 'NA'
ORDER BY DepDelay
DESC LIMIT 10")
# Print the class name of the query result.
cat("Class of top10delaysDF: ", class(top10delaysDF), "\n\n")
# Show the query result.
cat("Top 10 airline delays for 2007:\n\n")
head(top10delaysDF, 10)
# Output:
#
# Class of top10delaysDF: SparkDataFrame
#
# Top 10 airline delays for 2007:
#
# UniqueCarrier DepDelay Origin
# 1 AA 999 RNO
# 2 NW 999 EWR
# 3 AA 999 PHL
# 4 MQ 998 RST
# 5 9E 997 SWF
# 6 AA 996 DFW
# 7 NW 996 DEN
# 8 MQ 995 IND
# 9 MQ 994 SJT
# 10 AA 993 MSY
有关其他示例,请参阅 使用 R 中的 DataFrames 和表。