В чем разница между map и flatMap и хорошим вариантом использования для каждого?

apache-spark

117209 просмотра

15 ответа

Может кто-нибудь объяснить мне разницу между map и flatMap и каков хороший вариант использования для каждого?

Что означает «сгладить результаты»? Для чего это?

Автор: Eran Witkon Источник Размещён: 17.05.2019 03:09

Ответы (15)


156 плюса

Решение

Вот пример различия, как 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 в другой СДР длины N.

Например, он отображается из двух строк в две длины строки:

rdd.map(_.length).collect

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

Но flatMap(грубо говоря) преобразует СДР длины N в набор из N коллекций, а затем объединяет их в одну СДР результатов.

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"]

Поэтому входные и выходные СДР обычно имеют разные размеры 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

71 плюса

Обычно мы используем пример подсчета слов в hadoop. Я возьму тот же вариант использования и буду использовать, mapи flatMapмы увидим разницу в том, как он обрабатывает данные.

Ниже приведен пример файла данных.

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: СДР, созданный с помощью flatMap
  • wc: СДР создан с использованием 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Возвращает новый СДР, применяя данную функцию к каждому элементу СДР. Функция в mapвозвращает только один элемент.

flatMapАналогично map, он возвращает новый RDD, применяя функцию к каждому элементу RDD, но вывод выравнивается.

Автор: yoga Размещён: 15.01.2016 11:12

15 плюса

Если вы спрашиваете разницу между RDD.map и RDD.flatMap в Spark, map преобразует RDD размера N в другой размер N. например.

myRDD.map(x => x*2)

например, если myRDD состоит из Doubles.

В то время как flatMap может преобразовать RDD в другой, другой размер: например:

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

который вернет СДР размером 2 * N или

myRDD.flatMap(x =>if x<10 new Seq(2*x,3*x) else new Seq(x) )
Автор: Oussama Размещён: 24.04.2014 01:46

12 плюса

Используйте 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

8 плюса

mapвозвращает СДР с равным количеством элементов, а 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

6 плюса

map и flatMap похожи в том смысле, что они берут строку из входного RDD и применяют к ней функцию. Они отличаются тем, что функция на карте возвращает только один элемент, а функция в flatMap может возвращать список элементов (0 или более) в качестве итератора.

Кроме того, вывод flatMap сглаживается. Хотя функция в flatMap возвращает список элементов, flatMap возвращает RDD, в котором все элементы из списка отображаются плоским способом (не списком).

Автор: Bhasker Размещён: 01.09.2015 12:44

5 плюса

Это сводится к вашему первоначальному вопросу: что вы подразумеваете под сглаживанием ?

Когда вы используете 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

4 плюса

Разницу можно увидеть из приведенного ниже примера кода 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

2 плюса

Flatmap и Map преобразуют коллекцию.

Разница:

map (func)
Возвращает новый распределенный набор данных, сформированный путем передачи каждого элемента источника через функцию func.

flatMap (func)
Аналогично map, но каждый входной элемент может быть сопоставлен с 0 или более выходными элементами (поэтому func должен возвращать Seq, а не один элемент).

Функция преобразования:
map : один элемент в -> один элемент в.
flatMap : один элемент в -> 0 или более элементов (коллекция).

Автор: Ajit K'sagar Размещён: 24.10.2016 07:16

1 плюс

Для всех тех, кто хотел PySpark связанных:

Пример преобразования: flatMap

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

['Привет, чем занимаешься']

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

Traceback (последний вызов был последним): файл "", строка 1, в AttributeError: объект list не имеет атрибута split

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

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


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

[['привет', 'что', 'есть', 'ты', 'делаешь'], ['this', 'is', 'rak']]

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

['привет', 'что', 'есть', 'ты', 'делаешь', 'это', 'есть', 'rak']

Надеюсь, поможет :)

Автор: Rakshith N Gowda Размещён: 01.05.2017 04:55

1 плюс

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 плюса

карта :

@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();
        });

}

mapдобавляет a Monoк тому, что возвращается внутри, note здесь accountRepository.save(acc)возвращает a 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

-1 плюса

Разница в выводе карты и 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 плюса

  • map (func) Возвращает новый распределенный набор данных, сформированный путем передачи каждого элемента источника через функцию func Объявленный.

в то время как

  • flatMap (func) Аналогично map, но каждый входной элемент может быть сопоставлен с 0 или более выходными элементами, поэтому func должен возвращать последовательность, а не один элемент.
Автор: Kondas Lamar Jnr Размещён: 23.02.2018 03:48

-1 плюса

map: Возвращает новое RDD, применяя функцию к каждому элементу RDD. Функция в .map может вернуть только один элемент.

flatMap: Подобно карте, он возвращает новое RDD, применяя функцию к каждому элементу СДР, но вывод выравнивается.

Кроме того, функция 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()

Вывод: уведомление о / п сведено в единый список [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
Вопросы из категории :
32x32