Convert Spark DataFrame to Map in Scala

brooke-lark-212309.jpg

테이블에서 각 나이별 Count를 구하는 상황이었다. val ageGroup = finalDf.groupBy("나이").count() 과 같이 각 나이가 몇 번 출현하는지 세는 것은 크게 문제가 없었지만, 사람이 어려봤자 0살, 늙어봤자 200살이니 굳이 이것을 데이터프레임으로 들고있기 보다는 Scala built-in Map으로 변환하고 싶었다.

하지만 ageGroup: org.apache.spark.sql.DataFrame = [나이: int, count: bigint]와 같이, 나이는 int, count는 bigint 타입으로 출력되어, 이것을 Seq로 만든뒤 List로 만드니 List[Any] 로 캐스팅 되는 것을 확인했다. Scala에서는 List에 타입이 섞일 수 없기 때문인가보다.

ageGroup.collect.map(_.toSeq.toList)
res55: Array[List[Any]] = Array(List(31, 4), List(65, 10), List(53, 7), List(34, 6), List(28, 9), List(27, 7), List(26, 2), List(44, 16), List(47, 5), List(52, 3), List(40, 9), List(57, 11), List(54, 14), List(48, 13), List(64, 8), List(41, 15), List(43, 13), List(37, 13), List(61, 6), List(35, 5), List(55, 16), List(59, 9), List(39, 11), List(23, 1), List(49, 14), List(51, 8), List(63, 10), List(50, 4), List(45, 12), List(38, 7), List(25, 10), List(24, 5), List(62, 6), List(29, 11), List(32, 10), List(60, 11), List(56, 13), List(58, 5), List(33, 6), List(68, 5), List(42, 19), List(30, 4), List(66, 6), List(67, 8), List(46, 14), List(36, 14))
view raw 1.scala hosted with ❤ by GitHub

앞어 언급한 바와 같이, ageGroup.toSeq.toList로 맵핑하면 위에서 언급한 List[Any] 타입으로 나오는 것을 볼 수 있다.
ageGroup.collect.map(_.toSeq.toList)
.toMap
:77: error: Cannot prove that List[Any] <:< (T, U).
.toMap
^
view raw 2.scala hosted with ❤ by GitHub

여기서 곧바로 Map으로 변환하려고 하면, 맵의 타입을 지정할 수 없기 때문에 toMap을 부를 수 없다는 에러 메세지를 확인할 수 있다.
ageGroup.collect.map(_.toSeq.toList)
.map(x => (x(0).asInstanceOf[Int], x(1).asInstanceOf[Long]))
res59: Array[(Int, Long)] = Array((31,4), (65,10), (53,7), (34,6), (28,9), (27,7), (26,2), (44,16), (47,5), (52,3), (40,9), (57,11), (54,14), (48,13), (64,8), (41,15), (43,13), (37,13), (61,6), (35,5), (55,16), (59,9), (39,11), (23,1), (49,14), (51,8), (63,10), (50,4), (45,12), (38,7), (25,10), (24,5), (62,6), (29,11), (32,10), (60,11), (56,13), (58,5), (33,6), (68,5), (42,19), (30,4), (66,6), (67,8), (46,14), (36,14))
view raw 3.scala hosted with ❤ by GitHub

위와 같이 캐스팅을 해줘서 List[Any]를 (Int, Long) Tuple로 캐스팅하면!
ageGroup.collect.map(_.toSeq.toList)
.map(x => (x(0).asInstanceOf[Int], x(1).asInstanceOf[Long]))
.toMap
res60: scala.collection.immutable.Map[Int,Long] = Map(56 -> 13, 42 -> 19, 24 -> 5, 37 -> 13, 25 -> 10, 52 -> 3, 46 -> 14, 57 -> 11, 29 -> 11, 61 -> 6, 60 -> 11, 28 -> 9, 38 -> 7, 33 -> 6, 65 -> 10, 53 -> 7, 41 -> 15, 32 -> 10, 34 -> 6, 45 -> 12, 64 -> 8, 44 -> 16, 59 -> 9, 27 -> 7, 54 -> 14, 49 -> 14, 39 -> 11, 66 -> 6, 35 -> 5, 48 -> 13, 63 -> 10, 50 -> 4, 67 -> 8, 31 -> 4, 43 -> 13, 40 -> 9, 26 -> 2, 55 -> 16, 23 -> 1, 58 -> 5, 36 -> 14, 30 -> 4, 51 -> 8, 47 -> 5, 68 -> 5, 62 -> 6)
view raw 4.scala hosted with ❤ by GitHub

정상적으로 Map으로 변환되는 것을 확인할 수 있다.

Leave a Reply