map和flatMap有什么区别,每个用例都是一个很好的用例?

apache-spark

117209 观看

15回复

1328 作者的声誉

有人可以向我解释一下map和flatMap之间的区别以及每个的好用例是什么?

什么“压扁结果”是什么意思?到底有什么好处呢?

作者: Eran Witkon 的来源 发布者: 2014 年 3 月 12 日

回应 (15)


156

35308 作者的声誉

决定

以下是作为spark-shell会话的差异示例:

首先,一些数据 - 两行文字:

val rdd = sc.parallelize(Seq("Roses are red", "Violets are blue"))  // lines

rdd.collect

    res0: Array[String] = Array("Roses are red", "Violets are blue")

现在,map将长度为N的RDD转换为另一个长度为N的RDD。

例如,它将两行映射为两个行长度:

rdd.map(_.length).collect

    res1: Array[Int] = Array(13, 16)

但是flatMap(松散地说)将长度为N的RDD转换为N个集合的集合,然后将这些RDD展平为单个RDD结果。

rdd.flatMap(_.split(" ")).collect

    res2: Array[String] = Array("Roses", "are", "red", "Violets", "are", "blue")

我们每行有多个单词和多行,但最后我们得到一个单词输出数组

为了说明这一点,flatMapping从一组行到一组单词看起来像:

["aa bb cc", "", "dd"] => [["aa","bb","cc"],[],["dd"]] => ["aa","bb","cc","dd"]

因此,输入和输出RDD通常具有不同的尺寸flatMap

如果我们试图使用map我们的split函数,我们最终会得到嵌套结构(一个单词数组的RDD,带有类型RDD[Array[String]]),因为每个输入必须有一个结果:

rdd.map(_.split(" ")).collect

    res3: Array[Array[String]] = Array(
                                     Array(Roses, are, red), 
                                     Array(Violets, are, blue)
                                 )

最后,一个有用的特殊情况是使用可能不返回答案的函数进行映射,因此返回一个Option。我们可以flatMap用来过滤掉返回的元素,None并从返回的元素中提取值Some

val rdd = sc.parallelize(Seq(1,2,3,4))

def myfn(x: Int): Option[Int] = if (x <= 2) Some(x * 10) else None

rdd.flatMap(myfn).collect

    res3: Array[Int] = Array(10,20)

(这里注意到Option的行为类似于具有一个元素或零元素的列表)

作者: DNA 发布者: 19.03.2014 03:21

15

2364 作者的声誉

如果你在Spark中询问RDD.map和RDD.flatMap之间的区别,map会将大小为N的RDD转换为另一个大小为N的RDD。例如。

myRDD.map(x => x*2)

例如,如果myRDD由双打组成。

虽然flatMap可以将RDD转换为另一个不同大小的另一个:例如:

myRDD.flatMap(x =>new Seq(2*x,3*x))

这将返回大小为2 * N或的RDD

myRDD.flatMap(x =>if x<10 new Seq(2*x,3*x) else new Seq(x) )
作者: Oussama 发布者: 24.04.2014 01:46

6

61 作者的声誉

map和flatMap是相似的,从某种意义上说,它们从输入RDD中取一行并在其上应用一个函数。它们的区别在于map中的函数只返回一个元素,而flatMap中的函数可以返回一个元素列表(0或更多)作为迭代器。

此外,flatMap的输出是扁平的。虽然flatMap中的函数返回一个元素列表,但flatMap返回一个RDD,它以平面方式(不是列表)包含列表中的所有元素。

作者: Bhasker 发布者: 01.09.2015 12:44

71

1084 作者的声誉

通常我们在hadoop中使用字数统计示例。我将采取相同的使用情况,并会使用mapflatMap,我们将看到的区别是如何处理数据。

下面是示例数据文件。

hadoop is fast
hive is sql on hdfs
spark is superfast
spark is awesome

上面的文件将使用map和解析flatMap

运用 map

>>> wc = data.map(lambda line:line.split(" "));
>>> wc.collect()
[u'hadoop is fast', u'hive is sql on hdfs', u'spark is superfast', u'spark is awesome']

输入有4行,输出大小也是4,即N个元素==> N个元素。

运用 flatMap

>>> fm = data.flatMap(lambda line:line.split(" "));
>>> fm.collect()
[u'hadoop', u'is', u'fast', u'hive', u'is', u'sql', u'on', u'hdfs', u'spark', u'is', u'superfast', u'spark', u'is', u'awesome']

输出与地图不同。


让我们为每个键指定1作为值以获得单词计数。

  • fm:使用创建的RDD flatMap
  • wc:RDD使用创建 map
>>> fm.map(lambda word : (word,1)).collect()
[(u'hadoop', 1), (u'is', 1), (u'fast', 1), (u'hive', 1), (u'is', 1), (u'sql', 1), (u'on', 1), (u'hdfs', 1), (u'spark', 1), (u'is', 1), (u'superfast', 1), (u'spark', 1), (u'is', 1), (u'awesome', 1)]

map在RDD上wc会给出以下不需要的输出:

>>> wc.flatMap(lambda word : (word,1)).collect()
[[u'hadoop', u'is', u'fast'], 1, [u'hive', u'is', u'sql', u'on', u'hdfs'], 1, [u'spark', u'is', u'superfast'], 1, [u'spark', u'is', u'awesome'], 1]

如果map使用而不是,则无法获得单词计数flatMap

根据定义,map和之间的区别flatMap是:

map:它通过将给定函数应用于RDD的每个元素来返回新的RDD。函数map只返回一个项目。

flatMap:类似于map,它通过将函数应用于RDD的每个元素来返回新的RDD,但输出被展平。

作者: yoga 发布者: 15.01.2016 11:12

8

8120 作者的声誉

map返回相同数量元素的RDD,而flatMap不是。

flatMap过滤掉丢失或不正确数据的示例用例

用于map各种情况的示例用例,其中输入和输出的元素数量相同。

number.csv

1
2
3
-
4
-
5

map.py添加add.csv中的所有数字。

from operator import *

def f(row):
  try:
    return float(row)
  except Exception:
    return 0

rdd = sc.textFile('a.csv').map(f)

print(rdd.count())      # 7
print(rdd.reduce(add))  # 15.0

flatMap.py用于flatMap在添加之前过滤掉缺失的数据。与先前版本相比,添加的数字更少。

from operator import *

def f(row):
  try:
    return [float(row)]
  except Exception:
    return []

rdd = sc.textFile('a.csv').flatMap(f)

print(rdd.count())      # 5
print(rdd.reduce(add))  # 15.0
作者: wannik 发布者: 14.02.2016 11:20

12

5348 作者的声誉

使用test.md作为一个例子:

➜  spark-1.6.1 cat test.md
This is the first line;
This is the second line;
This is the last line.

scala> val textFile = sc.textFile("test.md")
scala> textFile.map(line => line.split(" ")).count()
res2: Long = 3

scala> textFile.flatMap(line => line.split(" ")).count()
res3: Long = 15

scala> textFile.map(line => line.split(" ")).collect()
res0: Array[Array[String]] = Array(Array(This, is, the, first, line;), Array(This, is, the, second, line;), Array(This, is, the, last, line.))

scala> textFile.flatMap(line => line.split(" ")).collect()
res1: Array[String] = Array(This, is, the, first, line;, This, is, the, second, line;, This, is, the, last, line.)

如果您使用的map方法,你会得到的线test.md,对flatMap方法,你会得到的单词数。

map方法类似于flatMap,它们都返回一个新的RDD。map方法经常使用返回一个新的RDD,flatMap方法经常使用拆分字。

作者: pangpang 发布者: 17.06.2016 07:41

2

573 作者的声誉

Flatmap和Map都会转换集合。

区别:

map(func)
返回通过函数func传递源的每个元素形成的新分布式数据集。

flatMap(func)
与map类似,但每个输入项可以映射到0个或更多输出项(因此func应返回Seq而不是单个项)。

转换函数:
map: - >一个元素out中的一个元素。
flatMap: - > 0或更多元素out(集合)中的一个元素。

作者: Ajit K'sagar 发布者: 24.10.2016 07:16

-1

181 作者的声誉

map和flatMap的输出差异:

1。flatMap

val a = sc.parallelize(1 to 10, 5)

a.flatMap(1 to _).collect()

输出:

 1, 1, 2, 1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10

2 . map:

val a = sc.parallelize(List("dog", "salmon", "salmon", "rat", "elephant"), 3)

val b = a.map(_.length).collect()

输出:

3 6 6 3 8
作者: ashu17188 发布者: 04.04.2017 11:22

1

19 作者的声誉

对于那些希望PySpark相关的人:

示例转换:flatMap

>>> a="hello what are you doing"
>>> a.split()

['你好','什么','是','你','做']

>>> b=["hello what are you doing","this is rak"]
>>> b.split()

回溯(最近一次调用最后一次):文件“”,第1行,在AttributeError中:'list'对象没有属性'split'

>>> rline=sc.parallelize(b)
>>> type(rline)

>>> def fwords(x):
...     return x.split()


>>> rword=rline.map(fwords)
>>> rword.collect()

[['你好','什么','是','你','做'],['这','是','rak']]

>>> rwordflat=rline.flatMap(fwords)
>>> rwordflat.collect()

['你好','什么','是','你','做','这','是','rak']

希望能帮助到你 :)

作者: Rakshith N Gowda 发布者: 01.05.2017 04:55

4

41 作者的声誉

从下面的示例pyspark代码可以看出差异:

rdd = sc.parallelize([2, 3, 4])
rdd.flatMap(lambda x: range(1, x)).collect()
Output:
[1, 1, 2, 1, 2, 3]


rdd.map(lambda x: range(1, x)).collect()
Output:
[[1], [1, 2], [1, 2, 3]]
作者: awadhesh pathak 发布者: 17.11.2017 11:00

-1

24 作者的声誉

  • map(func)返回一个新的分布式数据集,该数据集是通过声明的函数func传递源的每个元素而形成的.so map()是单个术语

田地

  • flatMap(func)与map类似,但每个输入项可以映射到0个或更多输出项,因此func应返回Sequence而不是单个项。
作者: Kondas Lamar Jnr 发布者: 23.02.2018 03:48

5

350 作者的声誉

它归结为你最初的问题:扁平化是什么意思

当您使用flatMap时,“多维”集合变为“一维”集合。

val array1d = Array ("1,2,3", "4,5,6", "7,8,9")  
//array1d is an array of strings

val array2d = array1d.map(x => x.split(","))
//array2d will be : Array( Array(1,2,3), Array(4,5,6), Array(7,8,9) )

val flatArray = array1d.flatMap(x => x.split(","))
//flatArray will be : Array (1,2,3,4,5,6,7,8,9)

你想使用flatMap时,

  • 您的地图功能会导致创建多层结构
  • 但你想要的只是一个简单 - 平面 - 一维结构,通过删除所有内部分组
作者: ramu 发布者: 03.03.2018 07:04

-1

5 作者的声誉

map:它RDD通过将函数应用于每个元素来返回一个新元素RDD。.map中的函数只能返回一个项目。

flatMap:与map类似,它RDD通过将函数应用于RDD的每个元素来返回new ,但输出被展平。

此外,函数in flatMap可以返回元素列表(0或更多)

例如:

sc.parallelize([3,4,5]).map(lambda x: range(1,x)).collect()

输出:[[1,2],[1,2,3],[1,2,3,4]]

sc.parallelize([3,4,5]).flatMap(lambda x: range(1,x)).collect()

输出:通知o / p在单个列表中展平[1,2,1,2,3,1,2,3,4]

资料来源:https//www.linkedin.com/pulse/difference-between-map-flatmap-transformations-spark-pyspark-pandey/

作者: Pushkar Deshpande 发布者: 26.06.2018 10:45

1

11 作者的声誉

RDD.map 返回单个数组中的所有元素

RDD.flatMap 返回数组数组中的元素

我们假设我们在text.txt文件中有文本为

Spark is an expressive framework
This text is to understand map and faltMap functions of Spark RDD

使用地图

val text=sc.textFile("text.txt").map(_.split(" ")).collect

输出:

text: **Array[Array[String]]** = Array(Array(Spark, is, an, expressive, framework), Array(This, text, is, to, understand, map, and, faltMap, functions, of, Spark, RDD))

使用flatMap

val text=sc.textFile("text.txt").flatMap(_.split(" ")).collect

输出:

 text: **Array[String]** = Array(Spark, is, an, expressive, framework, This, text, is, to, understand, map, and, faltMap, functions, of, Spark, RDD)
作者: veera 发布者: 12.09.2018 06:50

0

795 作者的声誉

地图:

@PutMapping(path="/update/{id}", consumes=MediaType.APPLICATION_JSON_VALUE)
public Mono<Account> update(@PathVariable Long id, @RequestBody Account account) {
    Mono<Account> accFound = accountRepository.findById(id);
    return accFound.map(acc -> {
        acc.setAccountBalance(account.getAccountBalance());
        return accountRepository.save(acc).block();
        });

}

mapMono在内部accountRepository.save(acc)返回的内容中添加一个,注意这里返回一个Mono,如果我不添加block(),该方法update最终返回Mono<Mono<Account>>- 在这种情况下编译错误。

flatMap:

@PutMapping(path="/update/{id}", consumes=MediaType.APPLICATION_JSON_VALUE)
public Mono<Account> update(@PathVariable Long id, @RequestBody Account account) {
    Mono<Account> accFound = accountRepository.findById(id);
    return accFound.flatMap(acc -> {
        acc.setAccountBalance(account.getAccountBalance());
        return accountRepository.save(acc);
        });

}

flatMap 只返回里面返回的内容。

希望它有助于理解它是一种非常基本的方式

作者: Vikash 发布者: 08.02.2019 08:35
32x32