Может ли кто-нибудь объяснить мне разницу между map и flatMap и что является хорошим вариантом использования для каждого?
Что означает "сгладить результаты"? Для чего это полезно?
Может ли кто-нибудь объяснить мне разницу между map и flatMap и что является хорошим вариантом использования для каждого?
Что означает "сгладить результаты"? Для чего это полезно?
 Вот пример разницы, как сеанс 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 ведет себя скорее как список, который имеет либо один элемент, либо ноль элементов)
Обычно мы используем пример подсчета слов в 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: СДР создан с использованием flatMapwc: СДР создан с использованием 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, возвращает новую СДР, применяя функцию к каждому элементу СДР, но вывод выравнивается.
Если вы задаете разницу между 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) )
Используйте 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 часто для использования разделенных слов.
Это сводится к вашему первоначальному вопросу: что вы подразумеваете под сглаживанием?
Когда вы используете 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, когда,
 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
map и flatMap аналогичны, в том смысле, что они берут строку из входного RDD и применяют к ней функцию. Их отличие заключается в том, что функция на карте возвращает только один элемент, а функция в flatMap может возвращать список элементов (0 или более) в качестве итератора.
Кроме того, вывод flatMap сплющен. Хотя функция в flatMap возвращает список элементов, flatMap возвращает RDD, который имеет все элементы из списка плоским способом (не список).
Разницу можно увидеть из приведенного ниже примера кода 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]]
все примеры хороши.... Вот хорошая наглядная иллюстрация... источник любезно: DataFlair обучение искры
Карта: карта - это операция преобразования в Apache Spark. Он применяется к каждому элементу СДР и возвращает результат как новый СДР. На карте разработчик операции может определить свою собственную бизнес-логику. Та же логика будет применяться ко всем элементам СДР.
 Функция map Spark RDD принимает один элемент в качестве входного процесса, обрабатывает его в соответствии с пользовательским кодом (указанным разработчиком) и возвращает один элемент за раз. Карта преобразует СДР длиной N в другой СДР длины N. Как правило, входные и выходные СДР имеют одинаковое количество записей.
 Пример 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.
 Пример 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)
Flatmap и Map преобразуют коллекцию.
Difference:
  карта (FUNC) 
Верните новый распределенный набор данных, сформированный путем передачи каждого элемента источника с помощью функции func.
  flatMap (FUNC) 
Подобно карте, но каждый элемент ввода может быть сопоставлен с 0 или более выходными элементами (поэтому func должен возвращать Seq, а не один элемент).
Функция преобразования: 
 карта: один элемент в → один элемент. 
 flatMap: один элемент в → 0 или более элементов (коллекция).
 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)
Для всех тех, кто хотел связать 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']
Надеюсь, это поможет:)
 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/
карта:
это метод более высокого порядка, который принимает функцию в качестве входных данных и применяет ее к каждому элементу в исходном СДР.
flatMap:
метод высшего порядка и операция преобразования, которая принимает входную функцию.
Разница в выходе карты и 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
в то время как