Belajar PySpark - Join Dataframe

belajar-pyspark-join-dataframe

Operasi join pada pyspark dataframe dilakukan dengan menggunakan fungsi spark.sql.DataFrame.join().

Jika mengacu pada klausa join dalam SQL statement berikut

SELECT * 
FROM Table1 INNER JOIN Table2 ON Table1.field1 = Table2.field2

 

Pada pyspark join, dataframe pemilik fungsi join akan menjadi dataframe kiri atau dataframe pertama (Table1 pada contoh di atas).

Fungsi join menerima 3 parameter :

  • other : dataframe yang akan di-join. Dataframe ini akan menjadi dataframe kanan (Table2 dalam contoh di atas).
  • on : Field yang akan menjadi join key
  • how : Jenis join, yaitu salah satu dari : inner, outer, cross, left_outer (bisa juga left atau leftouter), right_outer (bisa juga right atau rightouter), full, semi, anti


Data yang akan kita gunakan adalah dua dataframe, masing-masing berisi data mahasiswa dan data jurusan.

data1 = [['Agus','Fisika',130],
        ['Budi','Biologi',200],
        ['Bayu','Manajemen',180],
        ['Dedi','Akuntansi',50]]
kolom1 = ["nama","jurusan","nilai"]
df1 = spark.createDataFrame(data1,kolom1)
df1.show()

dataframe kiri

 

data2 = [['Fisika','FIS','MIPA'],
         ['Biologi','BIO','MIPA'],
         ['Manajemen','MAN','Ekonomi'],
         ['Bisnis','BIS','Ekonomi']]
kolom2 = ["jurusan","kode_jurusan","fakultas"]
df2 = spark.createDataFrame(data2,kolom2)
df2.show()

dataframe kanan

 

Inner Join

Secara default, pilihan tipe pada pyspark join adalah inner join. Kita bisa melakukan inner join dengan mengisi parameter dataframe kanan dan key join saja, seperti berikut ini. Perhatikan tanda yang digunakan untuk “sama dengan” adalah “==”

inner = df1.join(df2,df1.jurusan==df2.jurusan)
inner.show()

inner join dengan kondisi

 

Perhatikan bahwa dataframe hasil join akan menyertakan semua kolom dari dataframe kiri dan kanan, sehingga pasti akan terjadi duplikasi kolom yang menjadi key join. Jika terdapat nama kolom yang sama dari tabel kiri dan kanan, akan terjadi duplikasi kolom dengan nama yang sama.

Hal ini dapat mengakibatkan error ketika kita mencoba mengakses kolom tersebut.

inner["nama","jurusan"].show()

error duplikat nama kolom

 

Untuk menyertakan satu saja dari kolom key join, kita dapat menggunakan sintaks list untuk menyatakan parameter join key-nya.

Catatan hal ini hanya dapat digunakan jika nama join key di kedua dataframe sama.

df1.join(df2, ["jurusan"], "inner").show()

join menggunakan parameter berupa list

 

Join Dengan Lebih Dari 1 Key

Untuk melakukan join dengan lebih dari 1 key, gunakan & untuk ‘and’ dan | untuk ‘or’ untuk menggabungkan beberapa kondisi. Masing-masing kondisi dilingkupi tanda kurung.

data1 = [['Agus','Fisika','MIPA',130],
        ['Budi','Kimia','MIPA',200],
        ['Bayu','Mesin','Teknik',180],
        ['Dedi','Kimia','Teknik',50]]
kolom1 = ["nama","jurusan","fakultas", "nilai"]

data2 = [['Kimia','KIM','MIPA'],
         ['Fisika','FIS','MIPA'],
         ['Kimia','TKIM','Teknik'],
         ['Mesin','TMSN','Teknik']]

kolom2 = ["jurusan","kode_jurusan","fakultas"]

dfa = spark.createDataFrame(data1,kolom1)
dfb = spark.createDataFrame(data2,kolom2)

dfa.join(dfb,(dfa.jurusan==dfb.jurusan) &
              (dfa.fakultas==dfb.fakultas),"inner").show()

join dengan beberapa key

 

Jika nama kolom key di kedua dataframe sama, dapat digunakan list untuk menghindari duplikasi kolom output.

dfa.join(dfb, ["jurusan","fakultas"]).show()

join dengan parameter list

 

Left Outer Join

Left outer join atau left join mengembalikan semua baris dan kolom dari dataframe kiri, dan semua kolom dari dataframe kanan yang match. Untuk baris-baris dataframe kiri yang tidak menemukan pasangannya di dataframe kanan, kolom dataframe kanan akan diset null.

Untuk left join kita bisa menggunakan option “left”, “leftjoin”, atau “left_join”

df1.join(df2, ["jurusan"],"left").show()

left outer join dataframe

 

Right Outer Join

Right outer join atau right join mengembalikan semua baris dan kolom dari dataframe kanan, dan semua kolom dari dataframe kiri yang match. Untuk baris-baris dataframe kanan yang tidak menemukan pasangannya di dataframe kiri, kolom dataframe kiri akan diset null.

Untuk right outer join kita bisa menggunakan option “right”, “rightjoin”, atau “right_join”

df1.join(df2, ["jurusan"],"right").show()

right outer join dataframe

 

Full Outer Join

Full outer join atau full join mengembalikan semua baris dari dataframe kiri maupun kanan, baik ditemukan pasangannya maupun tidak.
Untuk record di dataframe kiri maupun kanan yang tidak ditemukan pasangannya, kolom yang bersesuaian akan diisi dengan null.

Nilai parameter yang dapat digunakan untuk full outer join adalah “full”, “fullouter”, atau “full_outer”

df1.join(df2, ["jurusan"],"full").show()

full outer join

 

Cross Join

Cross join menghasilkan cartesian product atau semua pasangan dari semua baris di dataframe kiri dan kanan, tanpa memperhatikan nilai kolomnya.

Jika kita memiliki 4 baris di dataframe kiri dan 4 di kanan, hasilnya adalah 4x4 = 16 baris.

Pada fungsi join di pyspark dataframe terdapat opsi “cross”, akan tetapi ternyata opsi ini tidak berfungsi sebagaimana mestinya. Untuk menggunakan opsi ini kita perlu mengisi parameter join key. Akan tetapi join dengan cara ini tidak menghasilkan cartesian product dari dua dataframe.

df1.join(df2, ["jurusan"],"cross").show()

opsi cross

 

Untuk mendapatkan hasil cartesian product dari kedua dataframe dengan fungsi join, kita hanya perlu mengisi nama dataframe kanan saja tanpa parameter on dan how seperti berikut ini :

df1.join(df2).show()

cross join

 

Atau kita bisa melakukannya dengan fungsi crossJoin()

df1.crossJoin(df2).show()

 

Mutating Join vs Filtering Join

Jika melihat dari duplikasi hasilnya, maka operasi join dapat dibagi menjadi dua jenis, yaitu mutating dan filtering.

Jenis-jenis join sebelumnya, yaitu inner, left, right, dan full join merupakan tipe mutating join. Yaitu operasi join yang akan menghasilkan satu record untuk setiap pasangan yang ditemukan. Ketika terjadi lebih dari 1 pasangan, maka join akan menghasilkan lebih dari 1 baris juga.

Ketika 1 baris dataframe kiri menemukan 2 baris pasangan di dataframe kanan, join akan mengembalikan 2 baris (duplikasi record kiri). Demikian juga jika 1 baris dataframe kanan menemukan 2 baris pasangan di dataframe kanan, akan dikembalikan 2 baris (duplikasi record kanan).

Misalnya untuk dataframe berikut ini

data_dup = [['Agus','Fisika',130],
        ['Budi','Biologi',200],
        ['Bayu','Manajemen',180],
        ['Dedi','Akuntansi',50],
        ['Andi','Manajemen',80]]

kolom = ["nama","jurusan","nilai"]

df_dup = spark.createDataFrame(data_dup,kolom)
df_dup.show()

dataref_dup = [['Biologi','BIO','MIPA'],
         ['Fisika','FIS','MIPA'],
         ['Bisnis','BIS','Ekonomi'],
         ['Manajemen','MAN','Ekonomi'],
         ['Manajemen','MNG','Ekonomi']]

kolom = ["jurusan","kode_jurusan","fakultas"]

ref_dup = spark.createDataFrame(dataref_dup,kolom)
ref_dup.show()

dataframe mutating dan filtering

 

Inner, left, right, maupun full join akan mengembalikan 4 baris data jurusan Manajemen.

Secara default mutating join juga mengembalikan semua kolom dari dataframe kiri maupun kanan.

df_dup.join(ref_dup, ["jurusan"], "inner").show()

inner join dengan duplikat

 

Pada filtering join, jika ditemukan lebih dari 1 match maka hanya akan dikembalikan 1 record saja. Filtering join hanya akan mengembalikan kolom dari satu dataframe saja. Terdapat 2 jenis filtering join yang biasa digunakan, yaitu (left) semi join dan (left) anti join.

 

Semi Join

Semi join atau disebut juga left semi join, adalah operasi join yang mengembalikan record-record dari dataframe kiri yang ditemukan pasangannya di dataframe kanan. Semi join juga hanya akan mengembalikan kolom-kolom dari dataframe kiri saja.

df_dup.join(ref_dup, ["jurusan"], "semi").show()

semi join

 

Perhatikan bahwa meskipun terdapat dua record untuk jurusan Manajemen di dataframe kanan, semi join tidak menduplikasi hasil joinnya.

Jika dataframe kiri berupa data transaksi dan dataframe kanan berupa data reference, proses ini semacam filtering record-record transaksi yang sesuai dengan data reference.

 

Anti Join

Anti join atau left anti join mengembalikan record-record dataframe kiri yang tidak ditemukan di dataframe kanan.

df_dup.join(ref_dup, ["jurusan"], "anti").show()

anti join


Jika dataframe kiri berupa data transaksi dan dataframe kanan berupa data reference, proses ini semacam filtering record-record transaksi yang tidak ditemukan referencenya.

Notebook untuk artikel ini dapat diakses di sini

 

Artikel sebelumnya: