Чи може хтось пояснити мені різницю між картою та flatMap та чим корисним є використання для кожного?
Що означає "вирівнювання результатів"? Для чого це добре?
Чи може хтось пояснити мені різницю між картою та 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перетворює RDD довжиною N в інший RDD довжини N.
Наприклад, він відображає з двох рядків на дві довжини рядків:
rdd.map(_.length).collect
res1: Array[Int] = Array(13, 16)
Але flatMap(слабко кажучи) перетворює RDD довжиною N в колекцію N колекцій, а потім згладжує їх в єдину RDD результатів.
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)
(тут зазначаючи, що Опція поводиться скоріше як список, який містить або один елемент, або нульові елементи)
["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: RDD створено за допомогою flatMapwc: RDD створено за допомогою 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)]
Тоді як flatMapRDD 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: Він повертає новий RDD, застосовуючи задану функцію до кожного елемента RDD. Функціяmapповертає лише один елемент.
flatMap: Подібно до цьогоmap, він повертає новий RDD, застосовуючи функцію до кожного елемента RDD, але вихід вирівнюється.
.map(lambda line:line.split(" "))не є масив рядків. Ви повинні перейти data.collect() на, wc.collectі ви побачите масив масивів.
wc.collect()?
Якщо ви запитуєте різницю між 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) )
Це зводиться до вашого первинного питання: що ви маєте на увазі під сплющенням ?
Коли ви використовуєте 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 повертає RDD з рівною кількістю елементів при цьому flatMap може не бути.
Приклад використання випадку дляflatMap фільтрації відсутніх або неправильних даних.
Приклад використання випадку дляmap використання в найрізноманітніших випадках, коли кількість елементів введення та виведення однакові.
номер.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 повертає RDD, який містить усі елементи зі списку рівним способом (а не список).
всі приклади хороші .... Ось приємна візуальна ілюстрація ... ввічливість джерела: Навчання DataFlair іскри
Карта: Карта - це операція перетворення в Apache Spark. Він застосовується до кожного елемента RDD і повертає результат як новий RDD. На карті розробник операцій може визначити власну логіку бізнесу. Така ж логіка буде застосована до всіх елементів RDD.
mapФункція Іскра ІРД приймає один елемент як процес введення його відповідно до користувальницького коду (вказаний розробником) і повертає один елемент за один раз. Карта перетворює RDD довжиною N в інший RDD довжини N. Вхідні та вихідні RDD зазвичай мають однакову кількість записів.
Приклад mapвикористання шкали:
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:
A flatMap- операція перетворення. Він застосовується до кожного елемента RDD і повертає результат як новий RDD. Це схоже на Map, але FlatMap дозволяє повернути 0, 1 або більше елементів з функції карти. В операції FlatMap розробник може визначити власну власну логіку бізнесу. Така ж логіка буде застосована до всіх елементів RDD.
Що означає "вирівнювання результатів"?
Функція FlatMap приймає один елемент як процес введення його відповідно до користувальницького коду (вказаного розробником) і одночасно повертає 0 або більше елементів. flatMap() перетворює RDD довжини N в інший RDD довжини M.
Приклад flatMapвикористання шкали:
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)
Подібно до карти, але кожен елемент введення може бути відображений до 0 або більше вихідних елементів (тому функція повинна повертати 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: "список" об'єкта не має атрибута "розділити"
>>> rline=sc.parallelize(b)
>>> type(rline)
>>> def fwords(x):
... return x.split()
>>> rword=rline.map(fwords)
>>> rword.collect()
[['привіт', 'що', 'є', 'ти', 'робиш]], [' це ',' є ',' рейк ']]
>>> rwordflat=rline.flatMap(fwords)
>>> rwordflat.collect()
['привіт', 'що', 'є', 'ти', 'робиш', 'це', 'є', 'рейк']
Сподіваюся, це допомагає :)
map: Він повертає нове RDD, застосовуючи функцію до кожного елемента RDD. Функція в .map може повертати лише один елемент.
flatMap: Подібно до карти, він повертає нове 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()
Вихід: повідомлення o / p вирівнюється в одному списку [1, 2, 1, 2, 3, 1, 2, 3, 4]
Джерело: https://www.linkedin.com/pulse/difference-between-map-flatmap-transformations-spark-pyspark-pandey/
карта:
- метод вищого порядку, який приймає функцію як вхідну інформацію і застосовує її до кожного елемента вихідної RDD.
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 Спарк . Взагалі, RDD-операції Spark моделюються після відповідних операцій збору Scala. Відповіді в stackoverflow.com/q/1059776/590203 , в яких обговорюється відмінність між ScalamapтаflatMapв ньому, можуть бути корисними для вас.