Может кто-нибудь объяснить мне разницу между 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"]
Поэтому входные и выходные СДР обычно имеют разные размеры flatMap.
Если бы мы попытались использовать mapнашу splitфункцию, мы бы получили вложенные структуры (СДР из массивов слов с типом 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 ведет себя скорее как список, который имеет либо один элемент, либо ноль элементов)
["a b c", "", "d"] => [["a","b","c"],[],["d"]]?
splitсписка строк приведет к созданию списка массивов)
Обычно мы используем пример подсчета слов в 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на 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, но вывод выравнивается.
.map(lambda line:line.split(" "))является не массив строк. Вы должны изменить data.collect() на wc.collectи вы увидите массив массивов.
wc.collect()?
Если вы спрашиваете разницу между 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) )
Это сводится к вашему первоначальному вопросу: что вы подразумеваете под сглаживанием ?
Когда вы используете 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, когда,
Используйте 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, они все возвращаются новый РДД. mapметод часто использовать, чтобы вернуть новый RDD, flatMapметод часто использовать разделенные слова.
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
map и flatMap похожи в том смысле, что они берут строку из входного RDD и применяют к ней функцию. Они отличаются тем, что функция на карте возвращает только один элемент, а функция в flatMap может возвращать список элементов (0 или более) в качестве итератора.
Кроме того, вывод flatMap сглаживается. Хотя функция в flatMap возвращает список элементов, flatMap возвращает RDD, в котором все элементы из списка отображаются плоским способом (не списком).
все примеры хороши .... Вот хорошая наглядная иллюстрация ... источник любезно: 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's 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)
Разницу можно увидеть из приведенного ниже примера кода 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]]
Flatmap и Map преобразуют коллекцию.
Разница:
map (func)
Возвращает новый распределенный набор данных, сформированный путем передачи каждого элемента источника через функцию func.
flatMap (func)
Аналогично map, но каждый входной элемент может быть сопоставлен с 0 или более выходными элементами (поэтому func должен возвращать Seq, а не один элемент).
Функция преобразования:
map : один элемент в -> один элемент в.
flatMap : один элемент в -> 0 или более элементов (коллекция).
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)
Для всех тех, кто хотел 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']
Надеюсь, поможет :)
map: Возвращает новое RDD, применяя функцию к каждому элементу RDD. Функция в .map может вернуть только один элемент.
flatMap: Подобно карте, он возвращает новое RDD, применяя функцию к каждому элементу СДР, но вывод выравнивается.
Также функция 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()
Вывод: уведомление о / п сведено в единый список [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
в то время как
RDD.mapиRDD.flatMapв Apache Spark . В целом, операции RDD в Spark моделируются после соответствующих операций сбора Scala. Ответы в stackoverflow.com/q/1059776/590203 , в которых обсуждается различие междуmapиflatMapв Scala, могут быть вам полезны.