누군가 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 개의 요소가있는 목록과 비슷하게 작동 함)
답변
일반적으로 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를 반환하지만 출력은 평평합니다.
답변
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을 사용하려고합니다.
- 지도 기능으로 다층 구조 생성
- 그러나 모든 내부 그룹을 제거하여 단순하고 평평한 1 차원 구조 만 있으면됩니다.
답변
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
답변
map과 flatMap은 입력 RDD에서 한 줄을 가져 와서 함수를 적용한다는 점에서 비슷합니다. 차이점은 map의 함수는 하나의 요소 만 반환하지만 flatMap의 함수는 요소 목록 (0 이상)을 반복자로 반환 할 수 있다는 것입니다.
또한 flatMap의 출력이 평탄화됩니다. flatMap의 함수는 요소 목록을 리턴하지만 flatMap은 목록의 모든 요소를 목록이 아닌 플랫 방식으로 갖는 RDD를 리턴합니다.