3
1

More than 3 years have passed since last update.

【Spark DataFrame】あるカラムを横持ちから縦持ちにする(Scala)

Posted at

はじめに

SparkDfで、DFのあるカラムついて横持ちから縦持ちにする場合、ちょっと手間取ったので備忘録をかねて記録しておきます。
一応、ソースコードはScalaですがPythonとかでもそんなに変わらないはずです。

データフレーム操作

テストDataFrameの作成

testDf.scala
val testDf = Seq(
    (1,"a",30,20),
    (2,"a",40,30),
    (3,"c",50,40),
    (4,"d",60,50),
    (2,"d",40,70),
    (2,"d",20,10),
    (1,"a",60,90)
   )
   .toDF("Column1", "Column2", "Column3","Column4")

/*
+-------+-------+-------+-------+
|Column1|Column2|Column3|Column4|
+-------+-------+-------+-------+
|      1|      a|     30|     20|
|      2|      a|     40|     30|
|      3|      c|     50|     40|
|      4|      d|     60|     50|
|      2|      d|     40|     70|
|      2|      d|     20|     10|
|      1|      a|     60|     90|
+-------+-------+-------+-------+
*/


縦持ち → 横持ち

縦持ち→横持ちは簡単で、pivot使えば簡単にできます。
使う際は「df.groupby().pivot().count()」のように3つのメソッドを用いる必要があります。

pivot.scala
val test2Df = testDf
.groupBy("Column1") 
.pivot("Column2") //横持ちにしたいカラム
.count() //集計関数
.na.fill(0) //ゼロ埋め

/*
+-------+---+---+---+
|Column1|  a|  c|  d|
+-------+---+---+---+
|      1|  2|  0|  0|
|      3|  0|  1|  0|
|      4|  0|  0|  1|
|      2|  1|  0|  2|
+-------+---+---+---+
*/

横持ち → 縦持ち

本題で、test2Dfがあったとして、何かの事情で縦持ちにしたい場合。
横持ち → 縦持ち はpivotのように一発でできる機能はなくて、ちょっと一手間?加えます。
使うものは、「selectExpr()」と「stack」です。
ソースコードは以下の通り。

unpivot.scala
val test3Df = test2Df
    .selectExpr(
        "Column1",//縦持ちの基準となる対象列
        "stack(3,'a',a,'c',c,'d',d)".//縦持ちとなる元
    )
/*
+-------+----+----+
|Column1|col0|col1|
+-------+----+----+
|      1|   a|   2|
|      1|   c|   0|
|      1|   d|   0|
|      3|   a|   0|
|      3|   c|   1|
|      3|   d|   0|
|      4|   a|   0|
|      4|   c|   0|
|      4|   d|   1|
|      2|   a|   1|
|      2|   c|   0|
|      2|   d|   2|
+-------+----+----+
*/

という風に変形できます。最初に、縦持ちの基準となる対象列を指定してあげて、次にstack()で、縦持ちとなる元を指定します。上の場合だと、Column1に対して、a,c,dを縦持ち化しています。stack()の3は縦持ちの個数(この場合a,c,dの3つ)、"a" "c" "d"は名前、a c dは、元のその列名の数値を参照しています(単純に"name1"とか文字列を入れるみたいなこともできます)。また、列名がDefaultではcol0とかになってますので、変更したい場合は、.withColumnRenamed("col0","〇〇")とかを使うと変更できます。

あとは、joinをうまく使ってやると、縦持ちから横持ちへの変更ができるんじゃないかなと思います。

参考リンク

How to Pivot and Unpivot a Spark DataFrame

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1