(转载)SPARKR,对RDD操作的介绍
原以为,用sparkR不能做map操作, 搜了搜发现可以。 lapply等同于map, 但是不能操作spark RDD. spark2.0以后, sparkR增加了 dapply, dapplycollect 可以操作spark RDD.
原文地址: http://www.2cto.com/kf/201605/508312.html
目前SparkR RDD实现了Scala RDD API中的大部分方法,可以满足大多数情况下的使用需求:
SparkR支持的创建RDD的方式有:
从R list或vector创建RDD(parallelize())
从文本文件创建RDD(textFile())
从object文件载入RDD(objectFile())
SparkR支持的RDD的操作有:
数据缓存,持久化控制:cache(),persist(),unpersist()
数据保存:saveAsTextFile(),saveAsObjectFile()
常用的数据转换操作,如map(),flatMap(),mapPartitions()等
数据分组、聚合操作,如partitionBy(),groupByKey(),reduceByKey()等
RDD间join操作,如join(), fullOuterJoin(), leftOuterJoin()等
排序操作,如sortBy(), sortByKey(), top()等
Zip操作,如zip(), zipWithIndex(), zipWithUniqueId()
重分区操作,如coalesce(), repartition()
其它杂项方法
和Scala RDD API相比,SparkR RDD API有一些适合R的特点:
SparkR RDD中存储的元素是R的数据类型。
SparkR RDD transformation操作应用的是R函数。
RDD是一组分布式存储的元素,而R是用list来表示一组元素的有序集合,因此SparkR将RDD整体上视为一个分布式的list。Scala API 中RDD的每个分区的数据由iterator来表示和访问,而在SparkR RDD中,每个分区的数据用一个list来表示,应用到分区的转换操作,如mapPartitions(),接收到的分区数据是一个list而不是iterator。
为了符合R用户经常使用lapply()对一个list中的每一个元素应用某个指定的函数的习惯,SparkR在RDD类上提供了SparkR专有的transformation方法:lapply()、lapplyPartition()、lapplyPartitionsWithIndex(),分别对应于Scala API的map()、mapPartitions()、mapPartitionsWithIndex()。
DataFrame APISpark 1.3版本引入了DataFrame API。相较于RDD API,DataFrame API更受社区的推崇,这是因为:
DataFrame的执行过程由Catalyst优化器在内部进行智能的优化,比如过滤器下推,表达式直接生成字节码。
基于Spark SQL的外部数据源(external data sources) API访问(装载,保存)广泛的第三方数据源。
使用R或Python的DataFrame API能获得和Scala近乎相同的性能。而使用R或Python的RDD API的性能比起Scala RDD API来有较大的性能差距。
Spark的DataFrame API是从R的 Data Frame数据类型和Python的pandas库借鉴而来,因而对于R用户而言,SparkR的DataFrame API是很自然的。更重要的是,SparkR DataFrame API性能和Scala DataFrame API几乎相同,所以推荐尽量用SparkR DataFrame来编程。
目前SparkR的DataFrame API已经比较完善,支持的创建DataFrame的方式有:
从R原生data.frame和list创建
从SparkR RDD创建
从特定的数据源(JSON和Parquet格式的文件)创建
从通用的数据源创建
将指定位置的数据源保存为外部SQL表,并返回相应的DataFrame
从Spark SQL表创建
从一个SQL查询的结果创建
支持的主要的DataFrame操作有:
·数据缓存,持久化控制:cache(),persist(),unpersist()
数据保存:saveAsParquetFile(), saveDF() (将DataFrame的内容保存到一个数据源),saveAsTable() (将DataFrame的内容保存存为数据源的一张表)
集合运算:unionAll(),intersect(), except()
Join操作:join(),支持inner、full outer、left/right outer和semi join。
数据过滤:filter(), where()
排序:sortDF(), orderBy()
列操作:增加列- withColumn(),列名更改- withColumnRenamed(),选择若干列 -select()、selectExpr()。为了更符合R用户的习惯,SparkR还支持用$、[]、[[]]操作符选择列,可以用$<列名> <- 的语法来增加、修改和删除列
RDD map类操作:lapply()/map(),flatMap(),lapplyPartition()/mapPartitions(),foreach(),foreachPartition()
数据聚合:groupBy(),agg()
转换为RDD:toRDD(),toJSON()
转换为表:registerTempTable(),insertInto()
取部分数据:limit(),take(),first(),head()
编程示例总体上看,SparkR程序和Spark程序结构很相似。
基于RDD API的示例
要基于RDD API编写SparkR程序,首先调用sparkR.init()函数来创建SparkContext。然后用SparkContext作为参数,调用parallelize()或者textFile()来创建RDD。有了RDD对象之后,就可以对它们进行各种transformation和action操作。下面的代码是用SparkR编写的Word Count示例:
library(SparkR) #初始化SparkContext sc <- sparkR.init("local", "RWordCount") #从HDFS上的一个文本文件创建RDD lines <- textFile(sc, "hdfs://localhost:9000/my_text_file") #调用RDD的transformation和action方法来计算word count #transformation用的函数是R代码 words <- flatMap(lines, function(line) { strsplit(line, " ")[[1]] }) wordCount <- lapply(words, function(word) { list(word, 1L) }) counts <- reduceByKey(wordCount, "+", 2L) output <- collect(counts)
基于DataFrame API的示例
基于DataFrame API的SparkR程序首先创建SparkContext,然后创建SQLContext,用SQLContext来创建DataFrame,再操作DataFrame里的数据。下面是用SparkR DataFrame API计算平均年龄的示例:library(SparkR) #初始化SparkContext和SQLContext sc <- sparkR.init("local", "AverageAge") sqlCtx <- sparkRSQL.init(sc) #从当前目录的一个JSON文件创建DataFrame df <- jsonFile(sqlCtx, "person.json") #调用DataFrame的操作来计算平均年龄 df2 <- agg(df, age="avg") averageAge <- collect(df2)[1, 1]
对于上面两个示例要注意的一点是SparkR RDD和DataFrame API的调用形式和Java/Scala API有些不同。假设rdd为一个RDD对象,在Java/Scala API中,调用rdd的map()方法的形式为:rdd.map(…),而在SparkR中,调用的形式为:map(rdd, …)。这是因为SparkR使用了R的S4对象系统来实现RDD和DataFrame类。
架构SparkR主要由两部分组成:SparkR包和JVM后端。SparkR包是一个R扩展包,安装到R中之后,在R的运行时环境里提供了RDD和DataFrame API。
图1 SparkR软件栈
SparkR的整体架构如图2所示。
图2 SparkR架构
R JVM后端SparkR API运行在R解释器中,而Spark Core运行在JVM中,因此必须有一种机制能让SparkR API调用Spark Core的服务。R JVM后端是Spark Core中的一个组件,提供了R解释器和JVM虚拟机之间的桥接功能,能够让R代码创建Java类的实例、调用Java对象的实例方法或者Java类的静态方法。JVM后端基于Netty实现,和R解释器之间用TCP socket连接,用自定义的简单高效的二进制协议通信。
R Worker
SparkR RDD API和Scala RDD API相比有两大不同:SparkR RDD是R对象的分布式数据集,SparkR RDD transformation操作应用的是R函数。SparkR RDD API的执行依赖于Spark Core但运行在JVM上的Spark Core既无法识别R对象的类型和格式,又不能执行R的函数,因此如何在Spark的分布式计算核心的基础上实现SparkR RDD API是SparkR架构设计的关键。
SparkR设计了Scala RRDD类,除了从数据源创建的SparkR RDD外,每个SparkR RDD对象概念上在JVM端有一个对应的RRDD对象。RRDD派生自RDD类,改写了RDD的compute()方法,在执行时会启动一个R worker进程,通过socket连接将父RDD的分区数据、序列化后的R函数以及其它信息传给R worker进程。R worker进程反序列化接收到的分区数据和R函数,将R函数应到到分区数据上,再把结果数据序列化成字节数组传回JVM端。
从这里可以看出,与Scala RDD API相比,SparkR RDD API的实现多了几项开销:启动R worker进程,将分区数据传给R worker和R worker将结果返回,分区数据的序列化和反序列化。这也是SparkR RDD API相比Scala RDD API有较大性能差距的原因。
DataFrame API的实现
由于SparkR DataFrame API不需要传入R语言的函数(UDF()方法和RDD相关方法除外),而且DataFrame中的数据全部是以JVM的数据类型存储,所以和SparkR RDD API的实现相比,SparkR DataFrame API的实现简单很多。R端的DataFrame对象就是对应的JVM端DataFrame对象的wrapper,一个DataFrame方法的实现基本上就是简单地调用JVM端DataFrame的相应方法。这种情况下,R Worker就不需要了。这是使用SparkR DataFrame API能获得和ScalaAPI近乎相同的性能的原因。
当然,DataFrame API还包含了一些RDD API,这些RDD API方法的实现是先将DataFrame转换成RDD,然后调用RDD 的相关方法。
展望SparkR目前来说还不是非常成熟,一方面RDD API在对复杂的R数据类型的支持、稳定性和性能方面还有较大的提升空间,另一方面DataFrame API在功能完备性上还有一些缺失,比如对用R代码编写UDF的支持、序列化/反序列化对嵌套类型的支持,这些问题相信会在后续的开发中得到改善和解决。如何让DataFrame API对熟悉R原生Data Frame和流行的R package如dplyr的用户更友好是一个有意思的方向。此外,下一步的开发计划包含几个大的特性,比如普渡大学正在做的在SparkR中支持Spark Streaming,还有Databricks正在做的在SparkR中支持ML pipeline等。SparkR已经成为Spark的一部分,相信社区中会有越来越多的人关注并使用SparkR,也会有更多的开发者参与对SparkR的贡献,其功能和使用性将会越来越强。
总结Spark将正式支持R API对熟悉R语言的数据科学家是一个福音,他们可以在R中无缝地使用RDD和Data Frame API,借助Spark内存计算、统一软件栈上支持多种计算模型的优势,高效地进行分布式数据计算和分析,解决大规模数据集带来的挑战。工欲善其事,必先利其器,SparkR必将成为数据科学家在大数据时代的又一门新利器。
(转载)SPARKR,对RDD操作的介绍的更多相关文章
- SPARKR,对RDD操作的介绍
(转载)SPARKR,对RDD操作的介绍 原以为,用sparkR不能做map操作, 搜了搜发现可以. lapply等同于map, 但是不能操作spark RDD. spark2.0以后, spar ...
- [转载]3.4 UiPath键盘操作的介绍和使用
一.键盘操作的介绍 模拟用户使用键盘操作的一种行为: 例如使用发送热键(Sendhotkey),输入信息 (Typeinto)的操作 二.键盘操作在UiPath中的使用 1.打开设计器,在设计库中新建 ...
- sqlite数据库操作详细介绍 增删改查,游标
sqlite数据库操作详细介绍 增删改查,游标 本文来源于www.ifyao.com禁止转载!www.ifyao.com Source code package com.example ...
- Spark编程模型及RDD操作
转载自:http://blog.csdn.net/liuwenbo0920/article/details/45243775 1. Spark中的基本概念 在Spark中,有下面的基本概念.Appli ...
- 【Spark】RDD操作具体解释4——Action算子
本质上在Actions算子中通过SparkContext运行提交作业的runJob操作,触发了RDD DAG的运行. 依据Action算子的输出空间将Action算子进行分类:无输出. HDFS. S ...
- 0802_转载-nn模块中的网络层介绍
0802_转载-nn 模块中的网络层介绍 目录 一.写在前面 二.卷积运算与卷积层 2.1 1d 2d 3d 卷积示意 2.2 nn.Conv2d 2.3 转置卷积 三.池化层 四.线性层 五.激活函 ...
- Java8 Stream 的一些操作和介绍
原创:转载需注明原创地址 https://www.cnblogs.com/fanerwei222/p/11858186.html Java8 Stream 是一个新的东西, 就是能够将常见的数据结构转 ...
- [.NET] 开头不讲"Hello Word",读尽诗书也枉然 : Word 操作组件介绍 - Spire.Doc
开头不讲"Hello Word",读尽诗书也枉然 : Word 操作组件介绍 - Spire.Doc [博主]反骨仔 [原文地址]http://www.cnblogs.com/li ...
- Spark学习(一)--RDD操作
标签(空格分隔): 学习笔记 Spark编程模型的两种抽象:RDD(Resilient Distributed Dataset)和两种共享变量(支持并行计算的广播变量和累加器). RDD RDD是一种 ...
随机推荐
- git无法提交问题
今天在git提交时遇到一个问题,如下图 根据它的提示手动删除index.lock文件就可以了. 那为什么会有这个index.lock文件呢?我就觉得是莫名其妙出现的,别人的解释是这样的: 在你进行某些 ...
- DotNetCore深入了解之一Startup类
一个典型的ASP.NET Core应用程序会包含Program与Startup两个文件.Program类中有应用程序的入口方法Main,其中的处理逻辑通常是创建一个WebHostBuilder,再生成 ...
- MFC原理第二讲.MFC的初始化过程
MFC原理第二讲MFC的初始化过程 一丶简介 通过上一讲.我们手工模拟了一个MFC程序. 但是上一讲留下了疑问. 就是WinMain在哪.以及消息处理在哪里. 这一节主要就是讲解Winmain在哪里. ...
- c# Console application Open/Get Url by Browser
C# url 用 浏览器打开.C#获取浏览器的url static void Main(string[] args) { string file = @"C:\Users\Hero\Desk ...
- 第3章 Linux上文件的权限管理
3.1 文件/目录的权限 3.1.1 文件的权限 每个文件都有其所有者(u:user).所属组(g:group)和其他人(o:other)对它的操作权限,a:all则同时代表这3者.权限包括读(r:r ...
- Python 通过 SMTP 发送邮件
Python版本:Python3.5.2 简介 SMTP是发送邮件的协议,Python 内置对 SMTP 的支持,可以发送纯文本邮件.HTML 邮件以及带附件的邮件. Python 对 SMTP 支持 ...
- iOS面试准备之思维导图
以思维导图的方式对iOS常见的面试题知识点进行梳理复习,文章xmind点这下载,文章图片太大查看不了也点这下载 你可以在公众号 五分钟学算法 获取数据结构与算法相关的内容,准备算法面试 公众号回复 g ...
- @property、@sythesize以及Ivar和@dynamic讲解(下)
下面仅仅是一些基本知识,可能有些知识用的比较少,不过知道怎么使用或者了解这个知识,还是不错的,毕竟技多不压身嘛!读完这篇文章大约需要5-10分钟左右!!! 一.@property 1.在头文件中: @ ...
- 二叉树的Python实现
树的定义与基本术语 树型结构是一类重要的非线性数据结构,其中以树和二叉树最为常用,是以分支关系定义的层次结构.树结构在客观世界中广泛存在,如人类社会的族谱和各种社会组织机构:在计算机领域中也有广泛 ...
- TensorFlow.js入门(一)一维向量的学习
TensorFlow的介绍 TensorFlow是谷歌基于DistBelief进行研发的第二代人工智能学习系统,其命名来源于本身的运行原理.Tensor(张量)意味着N维数组,Flow(流)意味着 ...