首页 > 其他分享 >MapReduce理解

MapReduce理解

时间:2024-11-02 11:09:06浏览次数:3  
标签:Map 辣椒酱 RDD MapReduce rdd 洋葱 理解

解释

下面是转载的一篇程序员给妻子讲解什么是MapReduce的对话,看完能大概明白

我问妻子:“你真的想要弄懂什么是MapReduce?” 她很坚定的回答说“是的”。 因此我问道:

我:你是如何准备洋葱辣椒酱的?(以下并非准确食谱,请勿在家尝试)

妻子:我会取一个洋葱,把它切碎,然后拌入盐和水,最后放进混合研磨机里研磨。这样就能得到洋葱辣椒酱了。

妻子:但这和MapReduce有什么关系?

我:你等一下。让我来编一个完整的情节,这样你肯定可以在15分钟内弄懂MapReduce.

妻子:好吧。

我:现在,假设你想用薄荷、洋葱、番茄、辣椒、大蒜弄一瓶混合辣椒酱。你会怎么做呢?

妻子:我会取薄荷叶一撮,洋葱一个,番茄一个,辣椒一根,大蒜一根,切碎后加入适量的盐和水,再放入混合研磨机里研磨,这样你就可以得到一瓶混合辣椒酱了。

我:没错,让我们把MapReduce的概念应用到食谱上。Map和Reduce其实是两种操作,我来给你详细讲解下。

Map(映射): 把洋葱、番茄、辣椒和大蒜切碎,是各自作用在这些物体上的一个Map操作。所以你给Map一个洋葱,Map就会把洋葱切碎。 同样的,你把辣椒,大蒜和番茄一一地拿给Map,你也会得到各种碎块。 所以,当你在切像洋葱这样的蔬菜时,你执行就是一个Map操作。 Map操作适用于每一种蔬菜,它会相应地生产出一种或多种碎块,在我们的例子中生产的是蔬菜块。在Map操作中可能会出现有个洋葱坏掉了的情况,你只要把坏洋葱丢了就行了。所以,如果出现坏洋葱了,Map操作就会过滤掉坏洋葱而不会生产出任何的坏洋葱块。

Reduce(化简):在这一阶段,你将各种蔬菜碎都放入研磨机里进行研磨,你就可以得到一瓶辣椒酱了。这意味要制成一瓶辣椒酱,你得研磨所有的原料。因此,研磨机通常将map操作的蔬菜碎聚集在了一起。

妻子:所以,这就是MapReduce?

我:你可以说是,也可以说不是。 其实这只是MapReduce的一部分,MapReduce的强大在于分布式计算。

妻子:分布式计算? 那是什么?请给我解释下吧。

我:没问题。

我:假设你参加了一个辣椒酱比赛并且你的食谱赢得了最佳辣椒酱奖。得奖之后,辣椒酱食谱大受欢迎,于是你想要开始出售自制品牌的辣椒酱。假设你每天需要生产10000瓶辣椒酱,你会怎么办呢?

妻子:我会找一个能为我大量提供原料的供应商。

我:是的..就是那样的。那你能否独自完成制作呢?也就是说,独自将原料都切碎? 仅仅一部研磨机又是否能满足需要?而且现在,我们还需要供应不同种类的辣椒酱,像洋葱辣椒酱、青椒辣椒酱、番茄辣椒酱等等。

妻子:当然不能了,我会雇佣更多的工人来切蔬菜。我还需要更多的研磨机,这样我就可以更快地生产辣椒酱了。

我:没错,所以现在你就不得不分配工作了,你将需要几个人一起切蔬菜。每个人都要处理满满一袋的蔬菜,而每一个人都相当于在执行一个简单的Map操作。每一个人都将不断的从袋子里拿出蔬菜来,并且每次只对一种蔬菜进行处理,也就是将它们切碎,直到袋子空了为止。

这样,当所有的工人都切完以后,工作台(每个人工作的地方)上就有了洋葱块、番茄块、和蒜蓉等等。

妻子:但是我怎么会制造出不同种类的番茄酱呢?

我:现在你会看到MapReduce遗漏的阶段—搅拌阶段。MapReduce将所有输出的蔬菜碎都搅拌在了一起,这些蔬菜碎都是在以key为基础的 map操作下产生的。搅拌将自动完成,你可以假设key是一种原料的名字,就像洋葱一样。 所以全部的洋葱keys都会搅拌在一起,并转移到研磨洋葱的研磨器里。这样,你就能得到洋葱辣椒酱了。同样地,所有的番茄也会被转移到标记着番茄的研磨器里,并制造出番茄辣椒酱。

作者:永远的冷冽 | 链接:https://www.jianshu.com/p/c2affdca8ed8 | 来源:简书

对应修饰符

理解了spark中map和reduce的含义,那么在pyspark代码中,哪些修饰符操作分别要进行map或reduce呢?

在 PySpark 中,map 和 reduce 操作的概念来自于函数式编程中的 MapReduce 模型。虽然 PySpark 提供了许多高级操作符,但它们本质上都可以归类为 map 或 reduce 操作。

Map 操作

map 操作是对每个元素应用一个函数,并返回一个新的 RDD。以下是一些常见的 map 操作:
map(func)
• 对 RDD 中的每个元素应用 func 函数,并返回一个新的 RDD。
• 示例:

rdd = sc.parallelize([1, 2, 3, 4])
mapped_rdd = rdd.map(lambda x: x * 2)
print(mapped_rdd.collect())  # 输出: [2, 4, 6, 8]

flatMap(func)
• 对 RDD 中的每个元素应用 func 函数,但 func 返回的是一个列表,然后将所有列表中的元素展平成一个 RDD。
• 示例:

rdd = sc.parallelize(["hello world", "hi there"])
flat_mapped_rdd = rdd.flatMap(lambda x: x.split())
print(flat_mapped_rdd.collect())  # 输出: ['hello', 'world', 'hi', 'there']

filter(func)
• 对 RDD 中的每个元素应用 func 函数,返回一个只包含满足条件的元素的新 RDD。
• 示例:

rdd = sc.parallelize([1, 2, 3, 4, 5])
filtered_rdd = rdd.filter(lambda x: x % 2 == 0)
print(filtered_rdd.collect())  # 输出: [2, 4]

union(other)
• 返回两个 RDD 的并集。
• 示例:

rdd1 = sc.parallelize([1, 2, 3])
rdd2 = sc.parallelize([3, 4, 5])
union_rdd = rdd1.union(rdd2)
print(union_rdd.collect())  # 输出: [1, 2, 3, 3, 4, 5]

Reduce 操作

reduce 操作是对 RDD 中的所有元素应用一个函数,最终返回一个单一的结果。以下是一些常见的 reduce 操作:
reduce(func)
• 对 RDD 中的所有元素应用 func 函数,最终返回一个单一的结果。
• 示例:

rdd = sc.parallelize([1, 2, 3, 4])
result = rdd.reduce(lambda x, y: x + y)
print(result)  # 输出: 10

fold(zero_value, func)
• 类似于 reduce,但提供了一个初始值 zero_value。
• 示例:

rdd = sc.parallelize([1, 2, 3, 4])
result = rdd.fold(0, lambda x, y: x + y)
print(result)  # 输出: 10

aggregate(zero_value, seq_op, comb_op)
• 更通用的聚合操作,适用于更复杂的聚合逻辑。
• 示例:

rdd = sc.parallelize([1, 2, 3, 4])
result = rdd.aggregate(
    (0, 0),  # 初始值 (sum, count)
    lambda acc, value: (acc[0] + value, acc[1] + 1),  # 序列操作
    lambda acc1, acc2: (acc1[0] + acc2[0], acc1[1] + acc2[1])  # 合并操作
)
print(result)  # 输出: (10, 4)

groupByKey()
• 对键值对 RDD 中的键进行分组,返回一个包含每个键及其对应值的迭代器的 RDD。
• 示例:

rdd = sc.parallelize([("a", 1), ("b", 2), ("a", 3)])
grouped_rdd = rdd.groupByKey().mapValues(list)
print(grouped_rdd.collect())  # 输出: [('a', [1, 3]), ('b', [2])]

reduceByKey(func)
• 对键值对 RDD 中的每个键应用 func 函数,返回一个包含每个键及其聚合值的 RDD。
• 示例:

rdd = sc.parallelize([("a", 1), ("b", 2), ("a", 3)])
reduced_rdd = rdd.reduceByKey(lambda x, y: x + y)
print(reduced_rdd.collect())  # 输出: [('a', 4), ('b', 2)]

join(other)
• 对两个键值对 RDD 进行内连接,返回一个包含共同键及其对应值的 RDD。
• 示例:

rdd1 = sc.parallelize([("a", 1), ("b", 2)])
rdd2 = sc.parallelize([("a", 3), ("c", 4)])
joined_rdd = rdd1.join(rdd2)
print(joined_rdd.collect())  # 输出: [('a', (1, 3))]

总结

• Map 操作:对每个元素应用一个函数,返回一个新的 RDD。常见的操作包括 map、flatMap、filter、union 等。
• Reduce 操作:对 RDD 中的所有元素应用一个函数,最终返回一个单一的结果。常见的操作包括 reduce、fold、aggregate、groupByKey、reduceByKey、join 等。

标签:Map,辣椒酱,RDD,MapReduce,rdd,洋葱,理解
From: https://www.cnblogs.com/thx2199/p/18521723

相关文章

  • Windows 基础(一):深入理解Windows,掌握命令行与Shell
    内容预览≧∀≦ゞWindows基础(一)声明导语一、Windows和Linux的区别二、Windows的ShellShell和终端的区别1.命令提示符(CMD)2.WindowsPowerShell3.WindowsTerminal4.WindowsSubsystemforLinux(WSL)三、Windows常用命令1.文件与目录操作2.文本处理3.......
  • 图吧垃圾佬理解的早期国产芯片历史(龙芯中科和同行的恩怨解析)
    额……老铁们,我图吧老捡国产芯片垃圾的了。最近有人问咱关于国产芯片发展故事的事,所以咱简单答疑了一下顺带做了个记录的整理,简单看下情况。水友:就是我有个同学,已经魔怔了,现在已经在同学群里说天玑吊打国产芯片了前几天说的是吊打9950x…垃圾佬:吊打国产芯片可能是真的,9950x雀......
  • 深入理解指针(1)
    1:内存和地址1:内存我们知道计算机上面的CPU在处理数据时,需要的数据是在内存中读取的,处理后的数据也会放回内存中,那我们买电脑时,电脑内存是8GB/16GB/32GB等,那这些内存空间如何高效管理呢?其实也是内存划分为一个个的内存单元,每个内存的大小取1个字节。一个bit(比特)位可以储存一......
  • 有Redis为什么还要本地缓存?谈谈你对本地缓存的理解?
    本地缓存是将数据存储在应用程序所在的本地内存中的缓存方式。既然,已经有了Redis可以实现分布式缓存了,为什么还需要本地缓存呢?接下来,我们一起来看。为什么需要本地缓存?尽管已经有Redis缓存了,但本地缓存也是非常有必要的,因为它有以下优点:速度优势:本地缓存直接利用本地内存,......
  • WebSocket详解:从前端到后端的全栈理解
    文章目录前言一、WebSocket简介1.1WebSocket的特点二、WebSocket的工作原理2.1握手过程2.2数据传输三、WebSocket在前端的应用四、WebSocket在后端的应用五、WebSocket的局限与解决方案结语前言随着互联网技术的发展,传统的HTTP协议在某些场景下的局限性逐渐显......
  • 论企业集成平台的理解与应用
    一、引言随着企业信息化建设的不断深入,企业在生产、管理和服务等各方面产生了大量的数据和应用系统。然而,不同系统间的数据孤岛问题,以及信息整合和协同操作的需求日益增加,使得企业集成平台(EnterpriseIntegrationPlatform,EIP)成为信息化建设中的关键基础设施。EIP作为一种......
  • Hadoop-MapReduce任务三种运行开发模式
    1、local模式数据在本地,代码也在本地,使用本机的电脑的资源运行我们的MR输入和输出路径指的都是本地路径,运行时耗费的资源也是本地资源。2、local模式2数据在hdfs上,代码在本地,使用本机的电脑的资源运行我们的MRSystem.setProperty("HADOOP_USER_NAME","root");......
  • 【深度学习】从公式推导来深入理解误差反向传播算法2:《深度学习入门基于Python的理论
    《深度学习入门基于Python的理论与实现》中实现了2层全连接神经网络的代码对MNIST数据集的28x28像素0-9手写数字灰度图像进行分类,本文将重点对代码中的two_layer_net类的gradient函数中的误差反向传播的代码进行公式推导验证。验证小批量数据的交叉熵损失函数对第2层权重......
  • Xor-FWT 的另一种理解方式
    Xor-FWT的另一种理解方式学习\(\text{Fennec'sAlgorithm}\)的额外收获,顺手记录一下。假设我们要求两个长度为\(n\)的数组的异或卷积,为方便起见令\(n=2^m\),也就是类似下面的形式\[C_k=\sum\limits_{i\oplusj}A_i\timesB_j\]考虑构造\(\mathbb{Z}_2^n\)中的向......
  • 深入理解计算机系统 3.6 数组分配和访问
    C语言中的数组是一种将标量数据聚集成更大数据类型的方式。C语言实现数组的方式非常简单,因此很容易翻译成机器代码。C语言一个不同寻常的特点是可以产生指向数组中元素的指针,并对这些指针进行运算。在机器代码中,这些指针会被翻译成地址计算。3.6.1 基本原则对于数据类型T和......