spark编程

创建RDD

# 内部创建
list1 = [1,2,3,4,5,6]
set1 = set(list1)
rdd1 = sc.parallelize(list1)
rdd2 = sc.parallelize(set1)
print(rdd1.collect())
print(rdd2.collect())

rdd2.getNumPartitions()    # 获取分区

# 从文件读取数据创建RDD
rdd3 = sc.textFile(r'D:\ws\spark\test.txt')
rdd3.count()  
rdd3.collect()

map,flatMap转换数据,sortBy()排序、collect()查询、take()查询某几个值

# map
rdd4 = sc.parallelize([1,3,4,9])
rdd4.collect()
rdd4_new = rdd4.map(lambda x:x**2)   #不改变行数
rdd4_new.collect()
 
# sortBy
rdd5 = sc.parallelize([(1,3),(45,3),(10,9)])
rdd5_new = rdd5.sortBy(lambda x:x[0]).collect()

print(rdd5_new)
print(rdd5.sortBy(lambda x:x[0],ascending=False,numPartitions=3).collect())  #降序
  • 小练习:读取两个记录成绩的文件中中的内容,以‘\t’进行拆分,再排序选择bigdata中成绩最高的五位同学的学号
# 读取
bigdata = sc.textFile(r'D:\ws\spark\result_bigdata.txt')
math = sc.textFile(r'D:\ws\spark\result_math.txt')
# bigdata.collect()
# math.collect()
# 拆分
bigdata_new = bigdata.map(lambda x:x.split('\t')).collect()
# 再排序选择
bigdata_new2 = bigdata_new.sortBy(lambda x:int((x[2])),ascending=False)
# print(bigdata_new2.collect())
# 选择前5名
bigdata_new2.map(lambda x:x[0]).take(5)

union()合并多个RDD,filter()进行过滤、distinct()进行去重

sc.parallelize([1,2,3,4,4,4,4,]).filter(lambda x:x==4).collect()
# out:[4, 4, 4, 4]
# 将两个文件中内容用union连接起来
bigdata_math = bigdata.union(math)
bigdata_math1 = bigdata_math.map(lambda x:x.split('\t'))
bigdata_math2 = bigdata_math1.filter(lambda x:int(x[2])==100)
bigdata_math2.collect()
# 选择得100分的同学
bigdata_math2.map(lambda x:x[0]).distinct().collect()

键值对与RDD,转换操作reduceByKey()、groupByKey()

rdd = sc.parallelize([('a',1),('b',2),('c',3),('a',12)])
rdd.keys().collect()
# out:['a', 'b', 'c', 'a']
rdd.values().collect()
# out:[1, 2, 3, 12]
 # reduceByKey内必须是一个函数,把key相同的,以+法合并起来  
rdd.reduceByKey(lambda x,y:x+y).collect()
 # groupByKey不带任何参数,  这是一个可迭代的对象  
rdd.groupByKey().collect()    
# out:[('b', <pyspark.resultiterable.ResultIterable at 0x296857dc1c8>),
# ('c', <pyspark.resultiterable.ResultIterable at 0x296857dce48>),
# ('a', <pyspark.resultiterable.ResultIterable at 0x296857dc688>)]  
g_rdd.map(lambda x:sum(x[1])).collect()    # 求value的和
g_rdd.map(lambda x:(x[0],sum(x[1]))).collect()   #输出元组形式
  • 输出每一位同学所有科目的总成绩
score = bigdata.union(math).map(lambda x:x.split('\t'))
score.map(lambda x:(x[0],int(x[2]))).reduceByKey(lambda x,y:x+y).collect() 

join()连接两个RDD,zip组合两个RDD、combineByKey合并

rdd1 = sc.parallelize([('a',1),('b',2),('c',3)])
rdd2 = sc.parallelize([('a',1),('d',4),('e',5)])
rdd1.join(rdd2).collect()        # join连接
rdd1.leftOuterJoin(rdd2).collect()    #左外连接
rdd1.rightOuterJoin(rdd2).collect()   #右外连接
rdd1.fullOuterJoin(rdd2).collect()    #全连接

# zip(拉链),若rdd1与rdd2长度、分区个数不一样长,报错
rdd1 = sc.parallelize(['a','b','c'])
rdd2 = sc.parallelize([1,2,3])
rdd1.zip(rdd2).collect()   

combinByKey 高阶函数,有三个参数:

  • createCombiner,这个函数把当前的值作为参数,此时我们可以对其做些附加操作(类型转换)并把它返回 (这一步类似于初始化操作)
  • mergeValue, 该函数把元素V合并到之前的元素C(createCombiner)上 (这个操作在每个分区内进行)
  • mergeCombiners,该函数把2个元素C合并 (这个操作在不同分区间进行)
# 输出每位同学的平均成绩
test = sc.parallelize([('panda',1),('panda',8),('pink',4),('pink',8),('pirate',5)])

# 使用CombineByKey计算数据中每个键的总和和计数 (key,(总和,累加器))
createCombiner = lambda v:(v,1)

mergeValue = lambda agg,v:(agg[0]+v,agg[1]+1)

mergeCombiners = lambda agg1,agg2:(agg1[0]+agg2[0],agg1[1]+agg2[1])

test_new = test.combineByKey(createCombiner,mergeValue,mergeCombiners)
test_new.collect()
# out:[('panda', (9, 2)), ('pink', (12, 2)), ('pirate', (5, 1))]
print(test_new.map(lambda x:x[0]).collect())      # 打印key值
# out:['panda', 'pink', 'pirate']
print(test_new.map(lambda x:x[1][0]).collect())   # 打印相同key的总和
# out:[9, 12, 5]
print(test_new.map(lambda x:x[1][1]).collect())   # 打印key的累加器
# out:[2, 2, 1]
# 平均值
test_new.map(lambda x:(x[0] ,x[1][0] / x[1][1])).collect()
# out:[('panda', 4.5), ('pink', 6.0), ('pirate', 5.0)]

Spark SQL

文件中有三列数据,分别是用户id(userid)、艺术家id(artistid)、用户听该歌次数(playcount),求一下三个小问:

  1. 统计非重复的用户id的个数
  2. 统计用户听过歌曲的总数
  3. 找出ID为“1000002”的用户最喜欢的10首歌曲(即播放次数最多的10首歌曲)
# 读取文件
df = sc.textFile(r'D:\ws\spark\user_artist_data\user_artist_data.txt')
df.take(4)

out>>> 		['1000002 1 55',
			 '1000002 1000006 33',
			 '1000002 1000007 8',
			 '1000002 1000009 144']
# 转换成DataFrame的形式
data = df.map(lambda x:x.split(' ')).map(lambda x:(x[0],x[1],int(x[2]))).toDF()  
# DataFrame列名重命名需用到的列名
columns = ['userid','artistid','playcount']
# DataFrame列名重命名
for x,y in zip(data.columns,columns):
    data = data.withColumnRenamed(x,y)
data.printSchema()   # 查看结构

out>>>		 root
			 |-- userid: string (nullable = true)
			 |-- artistid: string (nullable = true)
			 |-- playcount: long (nullable = true)

data.show(4) 

out>>>  		+-------+--------+---------+
				| userid|artistid|playcount|
				+-------+--------+---------+
				|1000002|       1|       55|
				|1000002| 1000006|       33|
				|1000002| 1000007|        8|
				|1000002| 1000009|      144|
				+-------+--------+---------+
				only showing top 4 rows

# 第一题
df1 = data.groupBy('userid').count()
df1.count()
out>>> 	148111

# 第二题
df2 = data.groupBy('userid').sum('playcount').show(4)
out>>> 	+-------+--------------+
		| userid|sum(playcount)|
		+-------+--------------+
		|1000280|           995|
		|1000665|          1419|
		|1000795|           238|
		|1000839|           528|
		+-------+--------------+
		only showing top 4 rows

# 第三题
# 注册临时表,表名为t_law
data.registerTempTable('t_law')
#  执行SQL语句
sqlContext = SparkSession(sc)
sqlContext.sql("select * from t_law where userid='1000002' order by playcount desc limit 10").show()
out>>> 			+-------+--------+---------+
				| userid|artistid|playcount|
				+-------+--------+---------+
				|1000002| 1000024|      329|
				|1000002| 1000010|      314|
				|1000002|    4209|      265|
				|1000002| 1000323|      236|
				|1000002|    1890|      223|
				|1000002|     242|      176|
				|1000002| 1000088|      157|
				|1000002| 1000315|      155|
				|1000002| 1001008|      151|
				|1000002|    3033|      145|
				+-------+--------+---------+

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值