Может кто-нибудь объяснить мне разницу между 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
: СДР, созданный с помощью 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
на 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, могут быть вам полезны.