spark.dataframe的一些常用操作(Scala)

前言

说起dataframe,大家一般会首先想起pandas.dataframe。随着数据科学越来越火热,大部分同学都使用过python去进行一些数据科学的实践,也应该会对dataframe的简单易用颇有好感。
然而pandas只能用于处理单机问题,面对工业级的海量数据处理和计算,就显得无能为力。
spark作为分布式计算框架,在工业界占据了比较主流的地位。spark同样也提供了dataframe供用户使用。
spark.dataframe目前在网络上资料还不是很多,在此总结一些spark2.1中常用的一些操作,希望能给读者提供一些帮助。

1.数据的读入

数据在spark上经常被写成.parquet的格式,这是一种分片格式,读入数据的操作一般是这样:

val path = "/user/xxx/xxx/xxx/"
val df = spark.read.parquet(path)

对于txt文件的读入,可以用以下的方法来操作,不过这样读入之后,dataframe的每一行会是单独的名为value的一列,需要进一步解析,这时候需要用到map函数(会在后面提到)

val txtPath = "xxxxxx"
val df = spark.read.text(txtPath)

如果需要自己生成一些数据的话,可以这样来写:

 val testDF = Seq(
      ("1","98:0:0:0:0:0:0:19:93:0:0","1"),
      ("2","98:0:0:0:0:0:0:0:0:0:0","1"),
      ("3","0:0:0:0:0:0:0:0:0:0:90","1"),
      ("4","0:0:0:40:0:40:0:12:0:0:0","1"),
      ("5","98:0:0:0:0:0:0:19:93:100:0","0"),
      ("6","0:0:0:100:0:0:0:0:0:0:1","0")
    ).toDF("id","info","flag")

这样就生成了一个6行3列的spark.dataframe,这种方法,一般用来进行测试操作。

2.dataframe内容的查看

以上述testDF为例,如果我们想查看testDF中所有的数据,可以这样操作:其中num为展现的行数,默认为20,false表示不进行信息的缩略。

testDF.show(num,false)

如果想看一个dataframe中有那些列,这些列是什么样的数据类型,这种时候可以使用:

testDF.printSchema

如果想知道dataframe的行数

testDF.count()

如果想只看特定某些列,要用到select方法

testDF.select("id","flag").show(10,false)

3.dataframe中的过滤

如果想选择dataframe中某列为某某的数据或大于或小于某某的数据

val newDF = testDF.filter(col("id")==="1")
val new1DF = testDF.filter(col("value")>=12)

对于多个条件,filter方法可以写在一起

val new2DF = testDF.filter(col("1")===2 && col("2")<=12)

对于dataframe中数据的去重,可以使用distinct方法,和python中的unique是一个意思

val newDF = testDF.distinct()

4.分组操作

分组操作使用的方法是groupBy,并且附带聚合操作agg
举个例子,我们有一个很大的数据集,是关于饮食的,每个用户过去一个月午餐的食量,类似于这样
date id weight
1 u1 23
1 u2 24
1 u3 88
2 u1 12
2 u2 19
2 u3 74
3 u1 42
3 u2 12
3 u3 19
我们想得到每个用户的均值食量,我们需要用到groupBy和agg

val newDF = foodDF.groupBy("id").agg(
	mean("weight") as "meanWeight"
)

agg操作就是说在以key进行分组后,对每个分组内的列进行计算,agg中可以同时进行多个操作,生成我们所需要的数据

5.map操作

前面刚刚讲过agg操作的思想相当于对列进行操作计算,map正好是相反的,map是对行进行操作的。
比如前文说过的,读取txt文件之后,可以txt文件存在很多列,但只会存在一个列(value)的dataframe,这时候我们就需要用map把这个dataframe解析成我们想要的那个。

val fineDF = notfineDF.map(line=>{
	val colArr = line.getString(0).split("\t")
	val col1 = colArr(0)
	val col2 = colArr(1)
	(col1,col2)
}).toDF("col1","col2")

最后

以上是spark.dataframe的一些常用的基础操作,通过这些操作的组合可以实现工作中绝大部分需求。
最后安利一下stackoverflow,很多不懂的问题都是在上面找到了答案,感谢那些乐于分享的同学们。

  • 6
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值