Membaca file berfomat csv merupakan hal yang sangat penting. Hal ini karena salah satu format file yang sering digunakan dalam pemrosesan ataupun analisa data adalah csv (comma-separated values). File csv adalah file teks yang mengandung data tabular, di mana baris mewakili record, dan tiap kolom dipisahkan oleh tanda koma atau karakter lain seperti misalnya tab, pipe, semikolon, dll.
Dalam tutorial ini kita akan mempelajari bagaimana membaca file csv dan memuatnya ke dalam DataFrame.
Membaca File csv Ke Dalam DataFrame
Untuk membaca file csv ke dalam pyspark DataFrame, kita bisa menggunakan fungsi spark.read.csv(namafile), atau spark.read.format(“csv”).load(namafile)
Kita akan memuat sebuah file csv tanpa header ke dalam dataframe dan menampilkan skema dataframe tersebut.
df = spark.read.csv("mhs.csv")
df.printSchema()
root
|-- _c0: string (nullable = true)
|-- _c1: string (nullable = true)
|-- _c2: string (nullable = true)
|-- _c3: string (nullable = true)
|-- _c4: string (nullable = true)
Perhatikan bahwa secara otomatis pyspark akan memberi nama kolom dengan _c0, _c1, dan seterusnya, dan secara default membuat semua kolom tersebut bertipe string.
df.show()
+-----+---+---+---+---+
| _c0|_c1|_c2|_c3|_c4|
+-----+---+---+---+---+
| Agus| F|100|150|150|
|Windy| F|200|150|180|
| Budi| B|200|100|150|
| Dina| F|150|150|130|
| Bayu| F| 50|150|100|
| Dedi| B| 50|100|100|
+-----+---+---+---+---+
Kita juga bisa menggunakan dataframe reader general dengan menggunakan fungsi format dan load
df = spark.read.format("csv").load("mhs.csv")
df.show()
+-----+---+---+---+---+
| _c0|_c1|_c2|_c3|_c4|
+-----+---+---+---+---+
| Agus| F|100|150|150|
|Windy| F|200|150|180|
| Budi| B|200|100|150|
| Dina| F|150|150|130|
| Bayu| F| 50|150|100|
| Dedi| B| 50|100|100|
+-----+---+---+---+---+
Membaca File csv Dengan Header
Untuk membaca file csv yang mengandung header, kita bisa menambahkan parameter header = True pada fungsi spark.read.csv, atau menggunakan fungsi option(“header”, True).
df1 = spark.read.csv("mhs_header.csv", header=True)
df1.printSchema()
root
|-- nama: string (nullable = true)
|-- kode_jurusan: string (nullable = true)
|-- nilai1: string (nullable = true)
|-- nilai2: string (nullable = true)
|-- nilai3: string (nullable = true)
df1.show()
+-----+------------+------+------+------+
| nama|kode_jurusan|nilai1|nilai2|nilai3|
+-----+------------+------+------+------+
| Agus| F| 100| 150| 150|
|Windy| F| 200| 150| 180|
| Budi| B| 200| 100| 150|
| Dina| F| 150| 150| 130|
| Bayu| F| 50| 150| 100|
| Dedi| B| 50| 100| 100|
+-----+------------+------+------+------+
Selain sebagai parameter, kita dapat juga menggunakan fungsi option(“header”, True).
Fungsi option menerima parameter berupa sepasang key-value, dimana key adalah nama opsi atau parameter yang akan kita beri nilai, dan value adalah nilai untuk opsi tersebut. Misalnya (“header”, True) atau (“maxColumns”, 1000).
df1 = spark.read \
.option("header",True) \
.csv("mhs_header.csv")
Note : Untuk menggunakan fungsi option(), letakkan fungsi ini sebelum fungsi csv(), atau sebelum fungsi load() jika kita menggunakan spark.read generik seperti di bawah ini.
df1 = spark.read \
.format("csv") \
.option("header",True) \
.load("mhs_header.csv")
Menentukan Tipe Kolom Secara Otomatis
Jika data yang kita loading sudah bersih, yaitu tiap kolom berisi data sesuai dengan tipe kolom yang seharusnya, maka kita bisa menentukan tipe kolom dataframe secara otomatis. Kita bisa menggunakan parameter inferSchema = True atau option(“inferSchema”, True)
df = spark.read.csv("mhs_notclean.csv",
header=True,
inferSchema=True)
df.show()
df.printSchema()
+-----+------------+------+------+------+
| nama|kode_jurusan|nilai1|nilai2|nilai3|
+-----+------------+------+------+------+
| Agus| F| 100| 150| 150.0|
|Windy| F| 200| 150| 180.0|
| Budi| B| 200| -| 150.0|
| Dina| F| 150| 150| 130.0|
| Bayu| F| 50| 150| 100.5|
| Dedi| B| 50| 100| 120.0|
+-----+------------+------+------+------+
root
|-- nama: string (nullable = true)
|-- kode_jurusan: string (nullable = true)
|-- nilai1: integer (nullable = true)
|-- nilai2: string (nullable = true)
|-- nilai3: double (nullable = true)
Terlihat bahwa spark menentukan tipe data setiap kolom sesuai dengan jenis datanya. Kolom “nilai2” dideteksi sebagai string karena pada record ketiga kolom “nilai2”-nya non numerik. Sedangkan kolom “nilai3” dideteksi sebagai double karena record ke-5 berupa desimal.
Ada beberapa hal yang perlu diperhatikan jika kita akan menggunakan opsi ini, diantaranya yaitu :
- Jika data yang akan di-load masih belum bersih, khususnya jika kolom yang seharusnya numerik mengandung karakter non-numerik, maka spark akan membuat kolom tersebut bertipe string. Untuk data yang belum bersih, biasanya semua kolom dibaca sebagai string terlebih dahulu, dan baru ditentukan tipenya setelah dibersihkan, dan jika memang dibutuhkan.
- Jika data yang akan di-load berukuran besar, opsi inferSchema = True dapat beresiko menurunkan kinerja secara signifikan dan memboroskan resource, karena spark harus membaca semua data untuk dapat menentukan tipe tiap kolom. Untuk data besar, sebaiknya kita mendefinisikan skema dataframe sebelum melakukan loading data.
Membaca File Dengan Delimiter Selain Koma
Untuk membaca file yang menggunakan delimiter lain, kita bisa menggunakan opsi separator atau sep. Misalnya sep = “;” untuk file dengan delimiter semicolon atau sep = “\t” untuk file dengan delimiter tab.
df = spark.read.option("header",True) \
.option("inferSchema",True) \
.option("sep", "\t") \
.csv("mhs.tsv")
df.show()
df.printSchema()
+-----+------------+------+------+------+
| nama|kode_jurusan|nilai1|nilai2|nilai3|
+-----+------------+------+------+------+
| Agus| F| 100| 150| 150.0|
|Windy| F| 200| 150| 180.0|
| Budi| B| 200| -| 150.0|
| Dina| F| 150| 150| 130.0|
| Bayu| F| 50| 150| 100.5|
| Dedi| B| 50| 100| 100.0|
+-----+------------+------+------+------+
root
|-- nama: string (nullable = true)
|-- kode_jurusan: string (nullable = true)
|-- nilai1: integer (nullable = true)
|-- nilai2: string (nullable = true)
|-- nilai3: double (nullable = true)
Mengganti Nilai Tertentu Dengan NULL
Kita bisa mengganti suatu nilai tertentu dengan nilai NULL pada saat loading dengan menggunakan parameter nullValue. Misalnya kita ingin membaca nilai "-" sebagai NULL, maka kita gunakan opsi nullValue = "-".
df = spark.read.csv("mhs_notclean.csv",
header=True,
inferSchema=True,
nullValue="-")
df.show()
df.printSchema()
+-----+------------+------+------+------+
| nama|kode_jurusan|nilai1|nilai2|nilai3|
+-----+------------+------+------+------+
| Agus| F| 100| 150| 150.0|
|Windy| F| 200| 150| 180.0|
| Budi| B| 200| NULL| 150.0|
| Dina| F| 150| 150| 130.0|
| Bayu| F| 50| 150| 100.5|
| Dedi| B| 50| 100| 120.0|
+-----+------------+------+------+------+
root
|-- nama: string (nullable = true)
|-- kode_jurusan: string (nullable = true)
|-- nilai1: integer (nullable = true)
|-- nilai2: integer (nullable = true)
|-- nilai3: double (nullable = true)
Pada contoh sebelumnya kolom nilai2 dideteksi sebagai string karena terdapat nilai “-”. Setelah kita tambahkan parameter nullValue="-" , nilai tersebut dibaca sebagai NULL dan tipe kolomnya dideteksi sebagai integer.
Tanda Quote Untuk Escape Kolom
Nilai suatu kolom terkadang mengandung karakter yang digunakan sebagai delimiter. Biasanya kolom ini akan diawali dan diakhiri dengan tanda quote. Secara default tanda quote yang dipakai adalah double quote (“). Misalnya file dengan delimiter koma dapat mengandung kolom bernilai : A,B,C. Dalam file kolom tersebut disimpan sebagai “A,B,C”. Misalnya :
col1,col2
001,"A,B,C"
002,A
003,"A,B"
Adakalanya file yang kita baca tidak menggunakan qouble quote sebagai escape kolom. Kita dapat menyesuaikan tanda quote yang dipakai dengan parameter quote
Misalnya data berikut ini :
nama,kode_jurusan,nilai1,nilai2,nilai3,kelas
Agus,F,100,150,150,'A,B'
Windy,F,200,150,180,'A,C'
Budi,B,200,-,150,'B,C'
Dina,F,150,150,130,'A,B'
Bayu,F,50,150,100.50,'A,C'
Dedi,B,50,100,120,'B,C'
Pada saat loading kita tambahkan parameter quote = " ' "
df = spark.read.csv("mhs_quote.csv",
header=True,
inferSchema=True,
nullValue="-",
quote="'")
df.show()
df.printSchema()
+-----+------------+------+------+------+-----+
| nama|kode_jurusan|nilai1|nilai2|nilai3|kelas|
+-----+------------+------+------+------+-----+
| Agus| F| 100| 150| 150.0| A,B|
|Windy| F| 200| 150| 180.0| A,C|
| Budi| B| 200| NULL| 150.0| B,C|
| Dina| F| 150| 150| 130.0| A,B|
| Bayu| F| 50| 150| 100.5| A,C|
| Dedi| B| 50| 100| 120.0| B,C|
+-----+------------+------+------+------+-----+
root
|-- nama: string (nullable = true)
|-- kode_jurusan: string (nullable = true)
|-- nilai1: integer (nullable = true)
|-- nilai2: integer (nullable = true)
|-- nilai3: double (nullable = true)
|-- kelas: string (nullable = true)
Selain contoh-contoh di atas, masih banyak parameter atau opsi yang bisa digunakan sesuai dengan kebutuhan. Daftar parameter yang bisa digunakan dapat dilihat di sini .
Notebook untuk tutorial ini dapat diakses di sini
Artikel sebelumnya