python + spark (一)

本文深入解析了Spark中RDD的各种操作,包括转换、行动操作、集合操作等,通过实例展示了如何使用map、filter、reduceByKey等函数,以及如何利用Broadcast变量和accumulator累加器提升并行处理效率。
from pyspark import SparkContext
sc = SparkContext()
intRdd = sc.parallelize([2,3,1,4,5])
intRdd.collect()
[2, 3, 1, 4, 5]
strRdd = sc.parallelize(['apple','orange','banana','apple'])
strRdd.collect()
['apple', 'orange', 'banana', 'apple']
def addOne(x):
    return x + 1
intRdd.map(addOne).collect()
[3, 4, 2, 5, 6]
intRdd.map(lambda x: x + 1).collect()
[3, 4, 2, 5, 6]
strRdd.map(lambda x: 'frult:' + x).collect()
['frult:apple', 'frult:orange', 'frult:banana', 'frult:apple']
intRdd.filter(lambda x : x < 3).collect()
[2, 1]
intRdd.filter(lambda x: x == 3).collect()
[3]
intRdd.filter(lambda x : 1 < x < 5).collect()
[2, 3, 4]
intRdd.filter(lambda x : x < 3 or x >= 5).collect()
[2, 1, 5]
strRdd.filter(lambda x : 'ra' in x).collect()
['orange']
intRdd.distinct().collect()
[4, 1, 5, 2, 3]
strRdd.distinct().collect()
['orange', 'banana', 'apple']
sRdd = intRdd.randomSplit([0.4,0.6])
sRdd[0].collect()
[2]
sRdd[1].collect()
[3, 1, 4, 5]
gRdd = intRdd.groupBy(lambda x: 'even' if(x%2 == 0) else 'odd').collect()
print(gRdd[0][0],sorted(gRdd[0][1]))
even [2, 4]
print(gRdd[1][0],sorted(gRdd[1][1]))
odd [1, 3, 5]
print(gRdd[0][0],sorted(gRdd[0][1]))
even [2, 4]
print(gRdd[1][0],sorted(gRdd[1][1]))
odd [1, 3, 5]
intRdd1 = sc.parallelize([3,1,2,5,5])
intRdd2 = sc.parallelize([5,6])
intRdd3 = sc.parallelize([2,7])
intRdd1.union(intRdd2).union(intRdd3).collect()
[3, 1, 2, 5, 5, 5, 6, 2, 7]
intRdd1.intersection(intRdd2).collect()
[5]
intRdd1.intersection(intRdd3).collect()
[2]
intRdd1.subtract(intRdd2).collect()
[1, 2, 3]
intRdd1.subtract(intRdd3).collect()
[1, 3, 5, 5]
intRdd1.cartesian(intRdd2).collect()
[(3, 5),
 (3, 6),
 (1, 5),
 (1, 6),
 (2, 5),
 (2, 6),
 (5, 5),
 (5, 5),
 (5, 6),
 (5, 6)]
intRdd2.cartesian(intRdd3).collect()
[(5, 2), (5, 7), (6, 2), (6, 7)]
intRdd1.cartesian(intRdd3).collect()
[(3, 2),
 (3, 7),
 (1, 2),
 (1, 7),
 (2, 2),
 (2, 7),
 (5, 2),
 (5, 2),
 (5, 7),
 (5, 7)]
intRdd.first()
2
intRdd.take(2)
[2, 3]
intRdd.takeOrdered(3)
[1, 2, 3]
intRdd.takeOrdered(3,key=lambda x:-x)
[5, 4, 3]
intRdd.stats
<bound method RDD.stats of ParallelCollectionRDD[0] at parallelize at PythonRDD.scala:194>
intRdd.stats()
(count: 5, mean: 3.0, stdev: 1.4142135623730951, max: 5.0, min: 1.0)
intRdd.min()
1
intRdd.max()
5
intRdd.stdev()
1.4142135623730951
intRdd.count()
5
intRdd.mean()
3.0
intRdd.sum()
15
kvRdd = sc.parallelize([(3,4),(3,6),(5,6),(1,2)])
kvRdd.collect()
[(3, 4), (3, 6), (5, 6), (1, 2)]
kvRdd.keys()
PythonRDD[81] at RDD at PythonRDD.scala:52
kvRdd.keys().collect()
[3, 3, 5, 1]
kvRdd.values().collect()
[4, 6, 6, 2]
kvRdd.values
<bound method RDD.values of ParallelCollectionRDD[80] at parallelize at PythonRDD.scala:194>
kvRdd.filter(lambda keyValue:keyValue[0] < 5).collect()
[(3, 4), (3, 6), (1, 2)]
kvRdd.filter(lambda kv:kv[0] <= 3).collect()
[(3, 4), (3, 6), (1, 2)]
kvRdd.filter(lambda kv:kv[1] < 5).collect()
[(3, 4), (1, 2)]
kvRdd.filter(lambda kv:kv[1] >= 2).collect()
[(3, 4), (3, 6), (5, 6), (1, 2)]
kvRdd.mapValues(lambda x: x**x).collect()
[(3, 256), (3, 46656), (5, 46656), (1, 4)]
kvRdd.mapValues(lambda x: x*x).collect()
[(3, 16), (3, 36), (5, 36), (1, 4)]
kvRdd.sortByKey(ascending=True).collect()
[(1, 2), (3, 4), (3, 6), (5, 6)]
kvRdd.sortByKey().collect()
[(1, 2), (3, 4), (3, 6), (5, 6)]
kvRdd.sortByKey(ascending=False).collect()
[(5, 6), (3, 4), (3, 6), (1, 2)]
kvRdd.reduceByKey(lambda x,y:x+y).collect()
[(5, 6), (1, 2), (3, 10)]
kvRdd1 = sc.parallelize([(3,4),(3,6),(5,6),(1,2)])
kvRdd2 = sc.parallelize([(3,8)])
kvRdd1.collect()
[(3, 4), (3, 6), (5, 6), (1, 2)]
kvRdd2.collect()
[(3, 8)]
kvRdd1.join(kvRdd2).collect()
[(3, (4, 8)), (3, (6, 8))]
kvRdd.leftOuterJoin(kvRdd2).collect()
[(1, (2, None)), (3, (4, 8)), (3, (6, 8)), (5, (6, None))]
kvRdd1.rightOuterJoin(kvRdd2).collect()
[(3, (4, 8)), (3, (6, 8))]
kvRdd1.subtractByKey(kvRdd2).collect()
[(1, 2), (5, 6)]
kvRdd1.first()
(3, 4)
kvRdd1.take(2)
[(3, 4), (3, 6)]
kvFirst = kvRdd1.first()
kvFirst
(3, 4)
kvFirst[1]
4
kvRdd1.countByKey()
defaultdict(int, {3: 2, 5: 1, 1: 1})
KV = kvRdd1.collectAsMap()
KV
{3: 6, 5: 6, 1: 2}
type(KV)
dict
KV[3]
6
KV[1]
2
kvRdd1.lookup(3)
[4, 6]
kvRdd1.lookup(1)
[2]
kvRdd1.lookup(5)
[6]
kvFrult = sc.parallelize([(1,'apple'),(2,'orange'),(3,'banana'),(4,'grape')])
frultMap = kvFrult.collectAsMap()
print('字典:'+str(frultMap))
字典:{1: 'apple', 2: 'orange', 3: 'banana', 4: 'grape'}
frultds = sc.parallelize([2,4,1,3])
print('水果编号:'+str(frultds.collect()))
水果编号:[2, 4, 1, 3]
frultName = frultds.map(lambda x: frultMap[x]).collect()
print('使用字典进行转换=>')
print('水果名称:'+str(frultName))
使用字典进行转换=>
水果名称:['orange', 'grape', 'apple', 'banana']

使用Broadcast广播变量的范例
Broadcast广播变量使用规则如下:
1.可以使用SparkContext.broadcast([初始值])创建
2.使用.value的方法来读取广播变量的值
3.Broadcast广播变量被创建后不能修改
使用Broadcast广播变量的范例与之前的范例类似,不同之处是使用sc.broadcast传入fruitMap作为参数,创建bcFruitMap广播变量,使用bcFruitMap.value(x)广播变量转换为fruitName水果名称

创建kvFruit
*这是水果编号与名称的Key-Value RDD *

kvFruit = sc.parallelize([(1,'apple'),(2,'orange'),(3,'banana'),(4,'grape')])

创建fruitMap
使用collectAsMap创建fruitMap字典

frultMap = kvFrult.collectAsMap()
print('对照表:' + str(frultMap))
对照表:{1: 'apple', 2: 'orange', 3: 'banana', 4: 'grape'}

将fruitMap字典转换为bcFrultMap广播变量
使用sc.broadcast传入frultMap参数,创建bcFrultMap广播变量

frultMap = kvFrult.collectAsMap()
bcFrultMap = sc.broadcast(frultMap)  # 使用sc.broadcast传入frultMap参数,创建bcFrultMap广播变量
print('字典:'+str(frultMap))  
字典:{1: 'apple', 2: 'orange', 3: 'banana', 4: 'grape'}

创建frultlds

frultlds = sc.parallelize([2,4,1,3])
print('水果编号:'+str(frultlds.collect()))
水果编号:[2, 4, 1, 3]

使用bcFruitMap.value字典进行转换

print('使用Broadcast 广播变量进行转换=>')
frultNames = frultlds.map(lambda x: bcFrultMap.value[x]).collect()
print('水果名称:'+str(frultNames))
使用Broadcast 广播变量进行转换=>
水果名称:['orange', 'grape', 'apple', 'banana']

在并行处理中,bcFruitMap广播变量会传到Worker Node机器,并且存储在内存中,后续在此Worker Node都可以使用这个bcFruitMap广播变量进行转换,这样可以节省很多内存和传送时间

accumulator累加器

计算总和是MapReduce常用的运算。为了方便进行处理,Spark特别提供了accumulator累加器共享变量(Shared variable),使用规则如下:

accumulator累加器的介绍
  • accumulator累加器可以使用SparkContext.accumulator([初始值])来创建
  • 使用.add()进行累加
  • 在task中,类如foreach循环中,不能读取累加器的值
  • 只有驱动程序,也就是循环外,才可以使用.value来读取累加器的值
accumulator累加器范例
  • 使用下列范例计算RDD的求和、计数
# 创建范例RDD
intRDD = sc.parallelize([3,1,2,5,5])
# 创建total累计器,初始值使用0.0,所以是Double类型
total = sc.accumulator(0.0)
# 创建num累加器,初始值使用0,所以是Int类型
num = sc.accumulator(0)
# 使用foreach传入i,针对没一下数据执行
# total累加intRDD元素的值、num累加intRDD元素的数量
intRDD.foreach(lambda i: [total.add(1),num.add(1)])
# 计算平均 = 求和 / 计数, 并显示总合、数量
avg = total.value / num.value
print('total =' + str(total.value) + ';num=' + str(num.value) +';avg=' + str(avg))
total =5.0;num=5;avg=1.0
### 使用 Python 结合 Spark 和 Hive 的数据分析方法 通过 PySpark,可以实现 Python 与 Apache Spark 的无缝集成。PySpark 提供了个用于分布式计算的强大框架,能够高效处理大规模数据集。当结合 Hive 时,可以通过 Spark SQL 访问存储在 Hive 中的数据并对其进行查询和分析。 以下是具体的方法: #### 1. 配置环境 为了使 Python 能够与 Spark 和 Hive 协同工作,需确保以下条件满足: - 安装好 Hadoop 并配置集群。 - 在第台机器的 `hadoop-2.5.0-cdh5.3.6/` 目录下初始化 NameNode 文件系统[^3]。 - 下载并安装 Spark,并设置 SPARK_HOME 环境变量。 - 同时需要下载 PySpark 库并通过 pip 或 conda 安装到本地环境中。 #### 2. 创建 SparkSession 对象 要访问 Hive 表中的数据,首先需要创建个支持 Hive 功能的 SparkSession 实例。这步骤允许 Spark SQL 查询直接操作 Hive 数据库表。 ```python from pyspark.sql import SparkSession spark = SparkSession.builder \ .appName("Python with Spark and Hive") \ .enableHiveSupport() \ .getOrCreate() ``` 上述代码片段展示了如何构建带有 Hive 支持功能的 SparkSession[^2]。 #### 3. 执行 HiveQL 查询语句 旦建立了 SparkSession,就可以像平常样运行标准的 HiveQL 命令来读取或者写入数据至 Hive 表中。 ```python df = spark.sql("SELECT * FROM your_hive_table LIMIT 10") df.show() ``` 此部分利用了 Spark SQL 来加载来自 Hive 的结构化数据,并将其转换成 DataFrame 形式以便进步加工处理。 #### 4. 处理复杂数据类型 对于更复杂的场景,比如涉及嵌套数组或其他高级别的 JSON 文档,则应考虑采用适合这些情况下的特定编码方式。例如,在定义模式时可以选择 ArrayType, MapType 等复合型字段描述符。 #### 5. 将结果保存回 Hive 完成所有必要的变换之后,还可以把最终的结果存回到新的 Hive 表里去。 ```python new_df.write.saveAsTable('your_new_hive_table') ``` 以上步骤说明了怎样借助于 Python 编程语言配合 Spark 工具包来进行基于 Hive 存储的大规模数据挖掘任务。 #### 注意事项 需要注意的是版本兼容性问题;这里假设使用的 Python 版本至少为 3.x ,而 Spark 及其组件也应当保持最新稳定发行版状态以获得最佳性能表现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值