Spark 主要操作的数据类型是RDD,使用RDD进行数据统计其实就那么几个方法,大多都是通过RDD.map()来解决,但是RDD内部的数据就仅仅是数据,没有结构Schema, 所以每一"列" 就只能通过RDD里的位置就判断。 通过 spark 提供的 Datafram API 可以提供table格式的数据,方便进行数据分析。
更重要的是 Spark更先进的库 pyspark.ML(我用pyspark实现)API处理的数据格式是dataframe,如果想使用spark ML,就需要Datafram 来准备
先看看RDD:
每一个字段在RDD内部存在于不同的位置,但是检索起来就很麻烦
SparkSession是 Spark Context, SqlContext, HiveContext 的入口
#生成SparkSession
sqlContext = SparkSession.builder.getOrCreate()
#生成Row数据类型,为每一个RDD内的数据定义数据类型
from pyspark.sql import Row
user_Rows = userRDD.map(lambda p:
Row(
userId = int(p[0]),
age = int(p[1]),
gender = p[2],
occupation = p[3],
zipcode = p[4]
)
)
user_Rows.take(5)
通过Row生成Dataframe
使用SQL操作, 需要把dataframe注册生成临时表
user_df.registerTempTable('user')
接下来就可以使用SQL语句对临时表User进行操作了
sqlContext.sql(
"""
select age,gender,occupation from user where age < 50 order by age limit 5
"""
).show(10)
1. 直接操作Datafram
# Dataframe.select方法
user_df.select('userid','occupation',"userId").show(10)
#pandas 写法 麻烦
user_df[user_df['userid'],user_df['occupation'],user_df['userId']].show(5)
2. SQL语句(sqlContext 就是创建的SparkSession, SparkSession.sql())
sqlContext.sql('select userid,occupation,gender from user').show(5)
#DataFrame
# .alias 为字段添加别名
df.select('userid','occupation','gender','age',(2019-df.age).alias("BOD")).show(5)
#SQL语句
sqlContext.sql("""
select userid,occupation,gender,age,2019-age BOD from user order by BOD
""").show(5)
1.Datafram.filter()方法,多个filter 等于 and
df.filter('occupation="engineer"').filter("gender='M'").filter("age='70'").show(20)
2. 单个filter,条件用&,|进行连接
df.filter((df.occupation=='engineer')&(df.gender=='M')&(df.age==70)).show()
3.SQL方法
sqlContext.sql(
"""
select age,gender,occupation,userId,zipcode from user where age==70 and gender="M" and occupation='engineer'
""").show()
RDD数据使用takeOrdered(个数,key)来排序
userRDD.takeOrdered(10,key=lambda x:int(x[1]))
1.Dataframe
使用 Dataframe.select().orderBy() 方法
df.select('userid','occupation','gender','age').orderBy('age').show(5)
#降序
df.select('userid','occupation','gender','age').orderBy('age', ascending=0).show(5)
#多个字段排序,age降序,age相同时gender升序
df.select('userid','occupation','gender','age').orderBy(['age','gender'],ascending=[0,1]).show(5)
2 SQL: Order By
RDD:用reduceByKey
DataFrame:用groupby
#RDD
userRDD.map(lambda x: (x[2],1)).reduceByKey(lambda x,y:x+y).filter(lambda x: x[1]>500).take(10)
#SQL方法
sqlContext.sql("""
select gender, count(gender) counts from user group by gender having counts>500
""").show()
#Dataframe
user_df.select(['gender','age']).groupby('gender').count().filter(col("count")>500).show()
SQL语句
#SQL语句
sqlContext.sql("""
select z.state, count(*) from user u left join zipcode_table z on u.zipcode = z.zipcode
where u.age < 50
group by z.state
""").show()
Dataframe
Join的Dataframe方法要生成一个新的dataframe然后进行操作
joined_df = user_df.join(zipcode_df,\
user_df.zipcode == zipcode_df.zipcode,'left_outer')
然后在通过filter,groupby进行筛选
joined_df.filter("state='NY'").show(10)
+---+------+-------------+------+-------+----------------+-----+-------+-----------+
|age|gender| occupation|userId|zipcode| city|state|zipcode|zipcodeType|
+---+------+-------------+------+-------+----------------+-----+-------+-----------+
| 29| M| other| 478| 10019| NEW YORK| NY| 10019| STANDARD|
| 22| F| healthcare| 405| 10019| NEW YORK| NY| 10019| STANDARD|
| 22| M| student| 327| 11101|LONG ISLAND CITY| NY| 11101| STANDARD|
| 48| M| educator| 656| 10314| STATEN ISLAND| NY| 10314| STANDARD|
| 27| F| writer| 617| 11201| BROOKLYN| NY| 11201| STANDARD|
| 35| F| other| 760| 14211| BUFFALO| NY| 14211| STANDARD|
| 30| F| writer| 557| 11217| BROOKLYN| NY| 11217| STANDARD|
| 27| M| marketing| 806| 11217| BROOKLYN| NY| 11217| STANDARD|
| 32| F| other| 155| 11217| BROOKLYN| NY| 11217| STANDARD|
| 23| M|administrator| 509| 10011| NEW YORK| NY| 10011| STANDARD|
+---+------+-------------+------+-------+----------------+-----+-------+-----------+
only showing top 10 rows
GroupBy 方法
GroupByState_df = joined_df.groupBy('state').count().filter(col("count")>20)
GroupByState_df.show(5)
+-----+-----+
|state|count|
+-----+-----+
| MN| 78|
| null| 35|
| VA| 27|
| MI| 23|
| WI| 22|
+-----+-----+
only showing top 5 rows
toPandas()方法
GroupByState_df = GroupByState_df.toPandas().set_index('state')