मानचित्र और फ़्लैटमैप के बीच अंतर और प्रत्येक के लिए एक अच्छा उपयोग मामला क्या है?


249

क्या कोई मुझे मानचित्र और फ़्लैटमैप के बीच का अंतर समझा सकता है और प्रत्येक के लिए एक अच्छा उपयोग मामला क्या है?

"परिणाम को समतल करता है" क्या मतलब है? ये किस काम के लिए अच्छा है?


4
जब से तुम स्पार्क टैग जोड़ा, मुझे लगता है कि आप के बारे में पूछ रहे हैं मान लेंगे RDD.mapऔर RDD.flatMapमें अपाचे स्पार्क । सामान्य तौर पर, स्पार्क का आरडीडी संचालन उनके संबंधित स्काला संग्रह संचालन के बाद तैयार किया जाता है। में जवाब stackoverflow.com/q/1059776/590203 , जो बीच के अंतर पर चर्चा mapऔर flatMapस्काला में, आप के लिए सहायक हो सकता है।
जोश रोसेन

1
यहाँ अधिकांश उदाहरण यह मानते हैं कि फ्लैटपाइप केवल संग्रह पर संचालित होता है, जो कि ऐसा नहीं है।
बून २

जवाबों:


195

यहाँ एक 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 में बदल देता है।

उदाहरण के लिए, यह दो लाइनों से दो लाइन-लंबाई में मैप करता है:

rdd.map(_.length).collect

    res1: Array[Int] = Array(13, 16)

लेकिन flatMap(शिथिल बोलना) लंबाई N के RDD को N संग्रहों के संग्रह में बदल देता है, फिर इन्हें परिणाम के एकल RDD में समतल कर देता है।

rdd.flatMap(_.split(" ")).collect

    res2: Array[String] = Array("Roses", "are", "red", "Violets", "are", "blue")

हमारे पास प्रति पंक्ति और एकाधिक पंक्तियों में कई शब्द हैं, लेकिन हम शब्दों के एकल आउटपुट सरणी के साथ समाप्त होते हैं

बस यह स्पष्ट करने के लिए कि, रेखाओं के संग्रह से शब्दों के संग्रह तक फ्लैट-मैपिंग इस प्रकार है:

["aa bb cc", "", "dd"] => [["aa","bb","cc"],[],["dd"]] => ["aa","bb","cc","dd"]

इसलिए इनपुट और आउटपुट आरडीडी आमतौर पर विभिन्न आकारों के लिए होंगे 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)

(यहां यह देखते हुए कि एक विकल्प एक सूची की तरह व्यवहार करता है जिसमें एक तत्व या शून्य तत्व होता है)


1
क्या मानचित्र देने के भीतर कॉलिंग विभाजित होगी ["a b c", "", "d"] => [["a","b","c"],[],["d"]]?
user2635088

1
हाँ - (लेकिन ध्यान दें कि मेरा अनौपचारिक संकेतन सिर्फ किसी प्रकार के संग्रह को इंगित करने के लिए था - वास्तव splitमें स्ट्रिंग्स की सूची पर मैपिंग से सूची की एक संख्या उत्पन्न होगी)
DNA

2
इसे लिखने के लिए धन्यवाद, यह सबसे अच्छा स्पष्टीकरण है जो मैंने उसी के बीच के अंतर को अलग करने के लिए पढ़ा है
राजीव

97

आमतौर पर हम हडूप में शब्द गणना उदाहरण का उपयोग करते हैं। मैं एक ही उपयोग के मामले का समय लगेगा और का उपयोग करेगा 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 एलिमेंट्स ==> एन एलिमेंट्स।

का उपयोग करते हुए 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 का उपयोग करके बनाया गया flatMap
  • wc: 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 लौटाता है, लेकिन आउटपुट चपटा होता है।


14
मुझे लगता है कि यह उत्तर स्वीकृत उत्तर से बेहतर है।
कृष्ण

15
पृथ्वी पर आप अवैध स्क्रीनशॉट क्यों बनायेंगे, जब आप सिर्फ आउटपुट टेक्स्ट को कॉपी पेस्ट कर सकते हैं?
nbubis

इसलिए फ्लैटपाइप () मैप () + "फ्लैटन" है और मुझे पता है कि इसका कोई मतलब नहीं है लेकिन क्या "फ्लैटन" फंक्शन का कोई प्रकार है जिसे हम मैप () के बाद उपयोग कर सकते हैं?
बुरुकोंगुन

2
आपके कोड में एक भ्रामक टाइपो है। का परिणाम .map(lambda line:line.split(" "))स्ट्रिंग की एक सरणी नहीं है। आप बदलना चाहिए data.collect() करने के लिए wc.collectऔर आप सरणियों की एक सरणी देखेंगे।
स्वदेश

1
हाँ, लेकिन आदेश का परिणाम अभी भी गलत है। क्या तुम चले wc.collect()?
स्वदेश

18

यदि आप स्पार्क में RDD.map और RDD.flatMap के बीच का अंतर पूछ रहे हैं, तो मानचित्र आकार N के RDD को N के किसी एक आकार में बदल देता है। जैसे।

myRDD.map(x => x*2)

उदाहरण के लिए, यदि myRDD डबल्स से बना है।

जबकि फ्लैटपाइप RDD को एक अलग आकार में बदल सकता है: उदा .:

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

जो 2 * N या आकार का RDD लौटाएगा

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

17

यह आपके शुरुआती सवाल को उबालता है : चपटेपन से आपका क्या मतलब है ?

जब आप फ्लैटपाइप का उपयोग करते हैं, तो एक "बहु-आयामी" संग्रह "एक-आयामी" संग्रह बन जाता है ।

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)

जब आप एक फ्लैटपाइप का उपयोग करना चाहते हैं,

  • मल्टी लेयर्ड स्ट्रक्चर्स बनाने में आपका मैप फंक्शन परिणाम देता है
  • लेकिन आप जो चाहते हैं, वह सभी आंतरिक समूहों को हटाकर एक सरल - सपाट - एक आयामी संरचना है

15

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अक्सर एक नए आरडीडी flatMapका उपयोग करने के लिए विधि, विभाजित शब्दों का उपयोग करने के लिए अक्सर विधि।


9

mapflatMapनहीं हो सकता है, जबकि तत्वों की समान संख्या का RDD लौटाता है ।

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इसके अलावा पहले से गायब डेटा को फ़िल्टर करने के लिए flatMap.py का उपयोग करता है। पिछले संस्करण की तुलना में कम संख्या में जोड़े जाते हैं।

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

8

नक्शा और फ्लैटपाइप समान हैं, इस अर्थ में वे इनपुट आरडीडी से एक लाइन लेते हैं और उस पर एक फ़ंक्शन लागू करते हैं। जिस तरह से वे भिन्न होते हैं वह यह है कि मानचित्र में फ़ंक्शन केवल एक तत्व देता है, जबकि फ्लैटपाइप में फ़ंक्शन तत्वों की एक सूची (0 या अधिक) को पुनरावृत्त के रूप में वापस कर सकता है।

इसके अलावा, फ्लैटपाइप का आउटपुट चपटा होता है। हालांकि फ्लैटपाइप में फ़ंक्शन तत्वों की एक सूची देता है, फ़्लैटबॉल एक RDD देता है जिसमें सूची से सभी तत्व एक फ्लैट तरीके से होते हैं (सूची नहीं)।


7

सभी उदाहरण अच्छे हैं .... यहाँ अच्छा दृश्य चित्रण है ... स्रोत शिष्टाचार: चिंगारी का डेटाफ़ेयर प्रशिक्षण

मानचित्र: अपाचे स्पार्क में एक नक्शा एक परिवर्तन ऑपरेशन है। यह RDD के प्रत्येक तत्व पर लागू होता है और यह नए RDD के रूप में परिणाम देता है। मैप में, ऑपरेशन डेवलपर अपने स्वयं के कस्टम व्यवसाय तर्क को परिभाषित कर सकता है। आरडीडी के सभी तत्वों पर एक ही तर्क लागू किया जाएगा।

स्पार्क आरडीडी mapफ़ंक्शन इनपुट तत्व के रूप में इसे कस्टम कोड के अनुसार लेता है (डेवलपर द्वारा निर्दिष्ट) और एक समय में एक तत्व देता है। मानचित्र लंबाई N के RDD को लंबाई N के एक और RDD में बदल देता है। इनपुट और आउटपुट RDDs में आमतौर पर समान संख्या में रिकॉर्ड होंगे।

यहां छवि विवरण दर्ज करें

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

फ़्लैटमैप:

A flatMapएक परिवर्तन प्रचालन है। यह RDD के प्रत्येक तत्व पर लागू होता है और यह नए के रूप में परिणाम देता है RDD। यह मैप के समान है, लेकिन फ्लैटपाइप मानचित्र फ़ंक्शन से 0, 1 या अधिक तत्वों को वापस करने की अनुमति देता है। FlatMap ऑपरेशन में, एक डेवलपर अपने स्वयं के कस्टम व्यवसाय तर्क को परिभाषित कर सकता है। आरडीडी के सभी तत्वों पर एक ही तर्क लागू किया जाएगा।

"परिणाम को समतल करता है" क्या मतलब है?

एक FlatMap फ़ंक्शन इनपुट तत्व के रूप में इसे कस्टम कोड (डेवलपर द्वारा निर्दिष्ट) के अनुसार लेता है और एक बार में 0 या अधिक तत्व देता है। flatMap() लंबाई N के RDD को लंबाई M के दूसरे RDD में बदल देता है।

यहां छवि विवरण दर्ज करें

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)

5

अंतर नीचे नमूना 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]]

3

फ्लैटमैप और मैप दोनों संग्रह को बदल देते हैं।

अंतर:

नक्शा (func)
एक नया वितरित डेटासेट लौटाएँ जो फ़ंक्शन के प्रत्येक तत्व को फ़ंक्शन func के माध्यम से पास करके बनता है।

फ्लैटपाइप (फंक)
नक्शे के समान है, लेकिन प्रत्येक इनपुट आइटम को 0 या अधिक आउटपुट आइटम पर मैप किया जा सकता है (इसलिए फंक को एकल आइटम के बजाय एक Seq लौटना चाहिए)।

परिवर्तन फ़ंक्शन:
मानचित्र : एक तत्व में -> एक तत्व बाहर।
फ्लैटपाइप : एक तत्व में -> 0 या अधिक तत्व बाहर (एक संग्रह)।


3

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

फ्लैटपाइप का उपयोग करना

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)

2

उन सभी के लिए जो पाइस्पार्क से संबंधित हैं:

उदाहरण परिवर्तन: फ्लैट मैप

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

['हैलो, आप क्या कर रहे हैं']

>>> b=["hello what are you doing","this is rak"]
>>> b.split()

ट्रेसबैक (सबसे हालिया कॉल अंतिम): फ़ाइल "", पंक्ति 1, एट्रीब्यूट में: 'सूची' ऑब्जेक्ट में कोई विशेषता नहीं है 'विभाजन'

>>> rline=sc.parallelize(b)
>>> type(rline)

>>> def fwords(x):
...     return x.split()


>>> rword=rline.map(fwords)
>>> rword.collect()

[['हैलो', 'क्या', 'हैं', 'तुम', 'कर'], ['यह', 'है', 'रक']]

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

['हैलो', 'क्या', 'हैं', 'तुम', 'कर', 'यह', 'है', 'राक']

आशा करता हूँ की ये काम करेगा :)


2

map: यह RDDप्रत्येक तत्व के लिए एक फ़ंक्शन लागू करके एक नया देता है RDD। इनमैप में फ़ंक्शन केवल एक आइटम वापस कर सकता है।

flatMap: मानचित्र के समान, यह RDD के प्रत्येक तत्व के लिए एक फ़ंक्शन लागूRDD करके एक नया रिटर्न देता है , लेकिन आउटपुट चपटा होता है।

इसके अलावा, फ़ंक्शन flatMapतत्वों की एक सूची लौटा सकता है (0 या अधिक)

उदाहरण के लिए:

sc.parallelize([3,4,5]).map(lambda x: range(1,x)).collect()

आउटपुट: [[१, २], [१, २, ३], [१, २, ३, ४]]

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/


0

नक्शा :

एक उच्च-क्रम विधि है जो एक फ़ंक्शन को इनपुट के रूप में लेती है और इसे स्रोत RDD में प्रत्येक तत्व पर लागू करती है।

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

flatMap:

एक उच्च-क्रम विधि और परिवर्तन ऑपरेशन जो एक इनपुट फ़ंक्शन लेता है।


-1

मैप और फ्लैटपाइप के आउटपुट में अंतर:

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

-1
  • नक्शा (func) एक नए वितरित वितरित डेटासेट को स्रोत के प्रत्येक तत्व को फंक्शन के माध्यम से घोषित करके लौटाएं। func.so map () केवल टर्म है।

whiles

  • flatMap (func) नक्शे के समान, लेकिन प्रत्येक इनपुट आइटम को 0 या अधिक आउटपुट आइटम पर मैप किया जा सकता है, इसलिए func को एक आइटम के बजाय एक अनुक्रम लौटना चाहिए।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.