pySpark记录

1、combineByKey使用

<pyspark>
x = sc.parallelize([('B',1),('B',2),('A',3),('A',4),('A',5)])
createCombiner = (lambda el:str(el))
mergeVal = (lambda aggr,el:aggr+";"+el)
mergeComb = (lambda agg1,agg2 : agg1+";"+agg2)
y = x.combineByKey(createCombiner,mergeVal,mergeComb)
print(y.collect())
#结果:[('A', '3;4;5'), ('B', '1;2')]
补一个元胞的例子

其中combineByKey(func1,func2,func3)应用如下(下面三段摘自http://blog.csdn.net/sicofield/article/details/50957349):
要理解combineByKey(),要先理解它在处理数据时是如何处理每个元素的。由于combineByKey()会遍历分区中的所有元素,因此每个元素的键要么还没有遇到过,要么就和之前的键相同。combineByKey()的处理流程如下:

如果是一个新的元素,此时使用createCombiner()来创建那个键对应的累加器的初始值。(!注意:这个过程会在每个分区第一次出现各个键时发生,而不是在整个RDD中第一次出现一个键时发生。)

如果这是一个在处理当前分区中之前已经遇到键,此时combineByKey()使用mergeValue()将该键的累加器对应的当前值与这个新值进行合并。

3.由于每个分区都是独立处理的,因此对于同一个键可以有多个累加器。如果有两个或者更多的分区都有对应同一个键的累加器,就需要使用用户提供的mergeCombiners()将各个分区的结果进行合并。
官方文档的API:

combineByKey(createCombiner,mergeValue,mergeCombiners,numPartitions=None, partitionFunc=)
Generic function to combine the elements for each key using a custom set of aggregation functions. Turns an RDD[(K, V)] into a result of type RDD[(K, C)], for a “combined type” C. Users provide three functions:
createCombiner, which turns a V into a C (e.g., creates a one-element list)
mergeValue, to merge a V into a C (e.g., adds it to the end of a list)
mergeCombiners, to combine two C’s into a single one. In addition, users can control the partitioning of the output RDD.
Note V and C can be different – for example, one might group an RDD of type (Int, Int) into an RDD of type (Int, List[Int]).

x = sc.parallelize([(“a”, 1), (“b”, 1), (“a”, 1)])
def add(a, b): return a + str(b)
sorted(x.combineByKey(str, add, add).collect())
结果:[(‘a’, ‘11’), (‘b’, ‘1’)]

怀疑combineByKey有问题
createCombiner = (lambda t:[t])
mergeVal = (lambda aggr,t:aggr.append(t))
mergeComb = (lambda agg1,agg2 : agg1+agg2)
x=sc.parallelize([('a',1),('a',1),('a',1),('a',1)])
y = x.combineByKey(createCombiner,mergeVal,mergeComb)
print y.collect()
结果:[('a', [1, 1, 1, 1])]
x=sc.parallelize([('a',1),('a',1),('a',1),('a',1),('a',1),('a',1),('a',1),('a',1),('a',1),('a',1),('a',1),('a',1),('a',1),('a',1),('a',1),('a',1)])
y = x.combineByKey(createCombiner,mergeVal,mergeComb)
print y.collect()
结果:
File "/Users/bingdada/spark/python/lib/pyspark.zip/pyspark/shuffle.py", line 302, in mergeCombiners
    d[k] = comb(d[k], v) if k in d else v
  File "<stdin>", line 1, in <lambda>
TypeError: can only concatenate list (not "NoneType") to list
解决:我不用list了 combine的时候拼成字符串,获取的时候再解析成list,可以。。。。。。。原因?

2、groupByKey后数据格式
groupByKey()后,value会生成一个python的可迭代对象,通过list()将其变为列表,列表中每个元素为与key对应的value。所以可能groupByKey()后常会跟着mapValues().

groupByKey().mapValues(lambda recommendItemList:getContextList(list(recommendItemList)))

3、join后数据格式
跟函数:

mergeRdd = orderPoiRdd.fullOuterJoin(clickPoiRdd).map(lambda uidAndordAndCli:formatRdd(uidAndordAndCli))
#其中uidAndOrdAndCli是join后的tuple(key,(orderPoiRddJoinVal,clickPoijoinVal)),所以join后参数个数可以整体看做为1

直接跟map:

#join后不跟函数直接跟map的时候也可以直接把元胞中的每一项写清
join(groupIdRdd).map(lambda (globalid,((T1_TIMESTAMP,T2_TIMESTAMP),d_num)

在join时经常会报以下错误:
(1)ValueError: too many values to unpack 好像是返回参数多与自己lamda中写死的参数个数;
(2)need more than two values to unpack 好像是返回参数少与自己lamda中写死的参数个数;
这两个哪个对应哪个有点混了,待我有机会再改。
4、mapValues拼接返回格式
5、测试
本地小数据运行测试:
如果数据来自textfile,直接拉几行数据本地测试;
如果数据来自hql,先查好部分数据,下载;把sql过程换成textFile读+分割过程:

#原代码#:
orderPoiRdd = getOrderPoiRdd(sqlCtx)
clickPoiRdd = getClickPoiRdd(sqlCtx)
mergeRdd = mergeClickAndOrder(orderPoiRdd,clickPoiRdd)
#测试用代码#:
orderPoiRdd = sc.textFile("test_Ord").map(lambda line:line.split('\t'))
clickPoiRdd = sc.textFile("test_Cli").map(lambda line:line.split('\t'))
# print orderPoiRdd.collect()
# print clickPoiRdd.collect()
orderPoiRdd = getOrderPoiRdd(orderPoiRdd)
clickPoiRdd = getClickPoiRdd(clickPoiRdd)
# print orderPoiRdd.collect()
# print clickPoiRdd.collect()
mergeRdd = mergeClickAndOrder(orderPoiRdd,clickPoiRdd)
print  mergeRdd.collect()

copy一份原代码修改用于测试,测试过程中发现的问题同步到原代码中。
用coalesce(1)算子,这样只有一个线程,看log不会乱

6、避免线上脏数据影响的处理
(1) 分割后数据域个数不对的过滤掉。
(2) textFile后要过滤为None或“”行
(3) 数据倾斜:先用reduceByKey查出/保存条数很多的key,用map广播出去这些key,如果这些key不重要,处理的时候滤掉就可以了;
否则可以考虑把这种key划分成小key.
(4) python使用list时,需要设置index越界的处理方式,因为在数据量大情况下是有可能出这个问题的,要让代码尽可能健壮
这里写图片描述
这个问题拿小数据可能看不出来,而且在用小数据收集结果不是collect()而是take(2)的形式也看不出来,所以小数据就直接collect吧。然后这种错误报错位置不一定准,比如下面这个报错在reduceByKey,但是看了很久reduceByKey没有错误,后来发现是上面一行报错。所以在觉得报错语句较肯定没有问题的时候可以考虑数据不合法的问题:
这里写图片描述
(5)时间 要注意有9999:99:99 这样的脏数据

7、特别容易弄错参数个数的情况

    mergedItemRdd = itemUserRdd.filter(lambda line:line is not None and len(line)>0
            ).map(lambda line:line.strip().split("*")
                                      ).combineByKey(createCombiner,mergeVal,mergeComb
                                                     ).mapValues(lambda timeList:sortTimeList(timeList)
                                                                 ).map(lambda item_userkey,timeStr:strEncode(item_userkey)+"\t"+strEncode(timeStr))

combineByKey之前是一个元胞,处理完后也是一个元胞,所以只有一个参数(如果之前是list也要注意),像上面只写元胞的两个元素就错了!!!
8、spark栈溢出讲的挺好的博客:
http://www.voidcn.com/blog/zy_zhengyang/article/p-6181356.html
9、没有解决的问题:
调用类的静态方法,报错:RuntimeError: uninitialized staticmethod object

About This Book, Learn why and how you can efficiently use Python to process data and build machine learning models in Apache Spark 2.0Develop and deploy efficient, scalable real-time Spark solutionsTake your understanding of using Spark with Python to the next level with this jump start guide, Who This Book Is For, If you are a Python developer who wants to learn about the Apache Spark 2.0 ecosystem, this book is for you. A firm understanding of Python is expected to get the best out of the book. Familiarity with Spark would be useful, but is not mandatory., What You Will Learn, Learn about Apache Spark and the Spark 2.0 architectureBuild and interact with Spark DataFrames using Spark SQLLearn how to solve graph and deep learning problems using GraphFrames and TensorFrames respectivelyRead, transform, and understand data and use it to train machine learning modelsBuild machine learning models with MLlib and MLLearn how to submit your applications programmatically using spark-submitDeploy locally built applications to a cluster, In Detail, Apache Spark is an open source framework for efficient cluster computing with a strong interface for data parallelism and fault tolerance. This book will show you how to leverage the power of Python and put it to use in the Spark ecosystem. You will start by getting a firm understanding of the Spark 2.0 architecture and how to set up a Python environment for Spark., You will get familiar with the modules available in PySpark. You will learn how to abstract data with RDDs and DataFrames and understand the streaming capabilities of PySpark. Also, you will get a thorough overview of machine learning capabilities of PySpark using ML and MLlib, graph processing using GraphFrames, and polyglot persistence using Blaze. Finally, you will learn how to deploy your applications to the cloud using the spark-submit command., By the end of this book, you will have established a firm understanding of the Spark Python API and how it can be used to build data-intensive applications., Style and approach, This book takes a very comprehensive, step-by-step approach so you understand how the Spark ecosystem can be used with Python to develop efficient, scalable solutions. Every chapter is standalone and written in a very easy-to-understand manner, with a focus on both the hows and the whys of each concept.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值