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

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

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

Ответ 1

Вот пример разницы, как сеанс 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"]

Поэтому входные и выходные 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 ведет себя скорее как список, который имеет либо один элемент, либо ноль элементов)

Ответ 2

Обычно мы используем пример подсчета слов в 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)]

Принимая во внимание, что flatMap на СДР 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]

Вы не можете получить количество слов, если вместо flatMap используется map.

Согласно определению, разница между map и flatMap составляет:

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

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

Ответ 3

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

myRDD.map(x => x*2)

например, если myRDD состоит из парных разрядов.

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

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

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

myRDD.flatMap(x =>if x<10 new Seq(2*x,3*x) else new Seq(x) )

Ответ 4

Используйте 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 часто для использования разделенных слов.

Ответ 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, когда,

  • Ваша функция карты приводит к созданию многослойных структур
  • но все, что вам нужно, это простая - плоская - одномерная структура, удалив ВСЕ внутренние группировки

Ответ 6

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

Ответ 7

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

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

Ответ 8

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

Ответ 9

все примеры хороши.... Вот хорошая наглядная иллюстрация... источник любезно: DataFlair обучение искры

Карта: карта - это операция преобразования в Apache Spark. Он применяется к каждому элементу СДР и возвращает результат как новый СДР. На карте разработчик операции может определить свою собственную бизнес-логику. Та же логика будет применяться ко всем элементам СДР.

Функция map Spark RDD принимает один элемент в качестве входного процесса, обрабатывает его в соответствии с пользовательским кодом (указанным разработчиком) и возвращает один элемент за раз. Карта преобразует СДР длиной N в другой СДР длины N. Как правило, входные и выходные СДР имеют одинаковое количество записей.

enter image description here

Пример map с использованием scala:

val x = spark.sparkContext.parallelize(List("spark", "map", "example",  "sample", "example"), 3)
val y = x.map(x => (x, 1))
y.collect
// res0: Array[(String, Int)] = 
//    Array((spark,1), (map,1), (example,1), (sample,1), (example,1))

// rdd y can be re writen with shorter syntax in scala as 
val y = x.map((_, 1))
y.collect
// res1: Array[(String, Int)] = 
//    Array((spark,1), (map,1), (example,1), (sample,1), (example,1))

// Another example of making tuple with string and it length
val y = x.map(x => (x, x.length))
y.collect
// res3: Array[(String, Int)] = 
//    Array((spark,5), (map,3), (example,7), (sample,6), (example,7))

FlatMap:

flatMap - это операция преобразования. Он применяется к каждому элементу СДР и возвращает результат как новый RDD. Он похож на Map, но FlatMap позволяет возвращать 0, 1 или более элементов из функции карты. В операции FlatMap разработчик может определить свою собственную бизнес-логику. Та же логика будет применяться ко всем элементам СДР.

Что значит "сгладить результаты"?

Функция FlatMap принимает один элемент в качестве входного, обрабатывает его в соответствии с пользовательским кодом (указанным разработчиком) и возвращает 0 или более элементов одновременно. flatMap() преобразует СДР длины N в другой СДР длины M.

enter image description here

Пример flatMap с использованием scala:

val x = spark.sparkContext.parallelize(List("spark flatmap example",  "sample example"), 2)

// map operation will return Array of Arrays in following case : check type of res0
val y = x.map(x => x.split(" ")) // split(" ") returns an array of words
y.collect
// res0: Array[Array[String]] = 
//  Array(Array(spark, flatmap, example), Array(sample, example))

// flatMap operation will return Array of words in following case : Check type of res1
val y = x.flatMap(x => x.split(" "))
y.collect
//res1: Array[String] = 
//  Array(spark, flatmap, example, sample, example)

// RDD y can be re written with shorter syntax in scala as 
val y = x.flatMap(_.split(" "))
y.collect
//res2: Array[String] = 
//  Array(spark, flatmap, example, sample, example)

Ответ 10

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

Difference:

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

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

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

Ответ 11

RDD.map возвращает все элементы в одном массиве

RDD.flatMap возвращает элементы в 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)

Ответ 12

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

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

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

['hello', 'what', 'are', 'you', 'doing']

>>> 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()

[['hello', 'what', 'are', 'you', 'doing'], ['this', 'is', 'rak']]

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

['hello', 'what', 'are', 'you', 'doing', 'this', 'is', 'rak']

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

Ответ 13

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

flatMap: Аналогично map, он возвращает новый RDD, применяя функцию к каждому элементу 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/

Ответ 14

карта:

это метод более высокого порядка, который принимает функцию в качестве входных данных и применяет ее к каждому элементу в исходном СДР.

http://commandstech.com/difference-between-map-and-flatmap-in-spark-what-is-map-and-flatmap-with-examples/

flatMap:

метод высшего порядка и операция преобразования, которая принимает входную функцию.

Ответ 15

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

Ответ 16

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

в то время как

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