[apache-spark] 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 개의 요소가있는 목록과 비슷하게 작동 함)


답변

일반적으로 hadoop에서 단어 수 예제를 사용합니다. 나는 동일한 유스 케이스를 사용 map하고 사용할 flatMap것이며 데이터를 처리하는 방법의 차이점을 볼 것입니다.

아래는 샘플 데이터 파일입니다.

hadoop is fast
hive is sql on hdfs
spark is superfast
spark is awesome

위의 파일은 mapand를 사용하여 구문 분석됩니다 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)]

반면 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:와 마찬가지로 mapRDD의 각 요소에 함수를 적용하여 새 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.pyadd.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.pyflatMap추가하기 전에 누락 된 데이터를 필터링하는 데 사용 합니다. 이전 버전에 비해 적은 수의 숫자가 추가됩니다.

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를 리턴합니다.