누군가 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의 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")
한 줄에 여러 단어가 있고 여러 줄이 있지만 단어의 단일 출력 배열로 끝납니다.
설명을 위해, 줄 모음에서 단어 모음으로의 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은 하나의 요소 또는 0 개의 요소가있는 목록과 비슷하게 작동 함)
["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
and를 사용하여 구문 분석됩니다 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를 사용하여 작성 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)]
반면 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
: RDD의 각 요소에 주어진 함수를 적용하여 새로운 RDD를 리턴합니다. 함수는map
하나의 항목 만 반환합니다.
flatMap
:와 마찬가지로map
RDD의 각 요소에 함수를 적용하여 새 RDD를 반환하지만 출력은 평평합니다.
.map(lambda line:line.split(" "))
문자열 배열이 아닙니다. 당신은 변경해야합니다 data.collect()
으로 wc.collect
당신은 배열의 배열을 볼 수 있습니다.
wc.collect()
?
Spark에서 RDD.map과 RDD.flatMap의 차이점을 묻는 경우 map은 N 크기의 RDD를 N 크기의 다른 것으로 변환합니다. 예.
myRDD.map(x => x*2)
예를 들어, myRDD가 Doubles로 구성된 경우입니다.
flatMap이 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) )
그것은 당신의 최초의 질문에 종기 : 당신이 병합 무슨 뜻 ?
flatMap을 사용하면 "다차원" 컬렉션이 "1 차원" 컬렉션이됩니다.
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
은와 유사하며 모두 새로운 RDD를 반환합니다. map
자주 사용하는 flatMap
메소드 는 새로운 RDD를 리턴하고, 종종 분리 단어를 사용하는 메소드입니다.
map
동일 flatMap
하지 않은 요소 수의 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.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
모든 예제가 훌륭합니다 ... 여기에 멋진 시각적 인 그림이 있습니다 ... 소스 예의 : 스파크의 DataFlair 교육
지도 :지도는 Apache Spark에서 변형 작업입니다. RDD의 각 요소에 적용되며 결과를 새 RDD로 리턴합니다. 맵에서 운영 개발자는 자신의 사용자 정의 비즈니스 로직을 정의 할 수 있습니다. RDD의 모든 요소에 동일한 논리가 적용됩니다.
Spark RDD map
함수는 사용자 정의 코드 (개발자가 지정한)에 따라 입력 프로세스로 하나의 요소를 가져와 한 번에 하나의 요소를 반환합니다. 맵은 길이 N의 RDD를 길이 N의 다른 RDD로 변환합니다. 입력 및 출력 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의 각 요소에 적용되며 결과를 new로 반환합니다 RDD
. Map과 비슷하지만 FlatMap을 사용하면 map 함수에서 0, 1 개 이상의 요소를 반환 할 수 있습니다. FlatMap 작업에서 개발자는 자신의 사용자 지정 비즈니스 논리를 정의 할 수 있습니다. RDD의 모든 요소에 동일한 논리가 적용됩니다.
"결과 평평"이란 무엇을 의미합니까?
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)
차이점은 샘플 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]]
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()
역 추적 (가장 최근 호출 마지막) : AttributeError : 'list'개체의 파일 "", 행 1에 '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
: 유사은 새를 리턴하는 매핑 RDD
하여 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()
출력 : 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 :
입력 함수를 취하는 고차 방법 및 변환 연산
map 및 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
에 아파치 스파크 . 일반적으로 Spark의 RDD 작업은 해당 Scala 수집 작업 후에 모델링됩니다. 스칼라 와 의 차이점을 설명하는 stackoverflow.com/q/1059776/590203 의 답변 이 도움이 될 수 있습니다.map
flatMap