Lewati ke konten utama

Kuasai PySpark withColumn() untuk Transformasi Kolom DataFrame

Pelajari cara menggunakan PySpark withColumn() secara efektif untuk menambah, memperbarui, dan mentransformasi kolom DataFrame dengan yakin. Mencakup sintaks, kinerja, dan praktik terbaik.
· 9 mnt Baca

Jelajahi bersama AI

PySpark DataFrame sangat penting saat Anda membangun pipeline yang dapat diskalakan di Spark. Satu hal utama yang perlu diingat adalah DataFrame bersifat immutable. Artinya, setelah Anda memiliki satu DataFrame, Anda tidak bisa mengubahnya secara langsung; Anda selalu mendapatkan DataFrame baru setiap kali melakukan perubahan. Di sinilah PySpark withColumn() berperan. Fungsi ini membantu Anda menambah, memperbarui, atau mengubah kolom, tetapi karena DataFrame tidak berubah di tempat, Anda selalu perlu menetapkan ulang hasilnya ke variabel baru.

Dalam tutorial ini, saya akan memandu Anda menggunakan withColumn() untuk membentuk dan menyetel dataset Anda, baik saat Anda membangun fitur, merapikan tipe data, atau menambahkan logika.

Apa itu withColumn() di PySpark?

Singkatnya, withColumn() mengembalikan DataFrame baru dengan kolom yang ditambahkan atau diganti. Karena DataFrame tidak bermutasi, Anda harus menetapkan nilai kembalian itu, df = df.withColumn(...).

Di balik layar, setiap pemanggilan withColumn() menambahkan proyeksi dalam rencana logis. Itu tidak masalah jika Anda hanya melakukan satu atau dua, tetapi merangkai banyak pemanggilan dapat membengkakkan rencana, membuat Spark berjalan jauh lebih lambat.

Baru di PySpark? Anda dapat menguasai dasar-dasarnya untuk menangani big data dengan mudah, dengan mempelajari cara memproses, men-query, dan mengoptimalkan dataset masif untuk analitik yang kuat di kursus Introduction to PySpark kami.

Penggunaan Inti PySpark withColumn()

Mari kita bahas cara utama Anda akan menggunakan withColumn():

Menambahkan kolom konstan

Misalnya Anda ingin menambahkan timestamp atau flag. Gunakan lit() atau typedLit() dari pyspark.sql.functions. Contohnya:

from pyspark.sql.functions import lit
df = df.withColumn("ingest_date", lit("2025-07-29"))

Membuat kolom dari data yang sudah ada

Mungkin Anda ingin nilai turunan, menggabungkan string, atau menghitung total. Anda bisa melakukan:

from pyspark.sql.functions import col, expr
df = df.withColumn("full_name", col("first_name") + expr(" ' ' + last_name"))

Transformasi aritmetika atau berbasis ekspresi juga termasuk di sini.

Menimpa kolom yang sudah ada

Jika Anda sudah memiliki kolom dan ingin mengubahnya, withColumn() akan langsung menggantinya:

df = df.withColumn("age", col("age").cast("integer"))

Tidak perlu drop lalu tambah lagi.

Mengubah tipe data

Mengganti tipe sebuah kolom itu mudah:

df = df.withColumn("price", col("price").cast("decimal(10,2)"))

Menurut saya ini sangat berguna saat membaca JSON atau CSV yang longgar di mana tipe datang sebagai string.

Jika Anda mencari contoh lebih lanjut tentang apa itu PySpark dan bagaimana menggunakannya dengan contoh, saya rekomendasikan tutorial Getting Started with PySpark kami.

Logika Kondisional dan Ekspresi when()

Ada kalanya Anda perlu melakukan lebih dari sekadar aritmetika sederhana. Mungkin Anda sedang membangun kolom status berdasarkan skor. Atau menandai entri berdasarkan campuran aturan. Di sinilah when() dari pyspark.sql.functions berperan. Anggap saja seperti pernyataan IF. Anda bisa memasangkannya dengan otherwise() untuk mencakup banyak jalur.

Begini tampilannya:

from pyspark.sql.functions import when
df = df.withColumn(
    "grade",
    when(col("score") >= 90, "A")
    .when(col("score") >= 80, "B")
    .when(col("score") >= 70, "C")
    .otherwise("F")
)

Kodenya hampir terbaca seperti bahasa Inggris biasa: “Jika skor minimal 90, maka A. Jika 80, maka B. Lanjutkan… dan jika tidak ada yang cocok, beri F.” Ekspresif, dan Spark mengubah logika itu menjadi ekspresi efisien di balik layar. Tanpa loop bersarang, tanpa pemanggilan apply(), hanya DAG yang bersih dan rencana eksekusi yang jelas.

Ini berguna saat Anda ingin menghindari beralih ke SQL atau membuat kode berantakan dengan UDF.

Anda dapat mempelajari cara memanipulasi data dan membuat set fitur machine learning di Spark menggunakan SQL di Python dari tutorial Introduction to Spark SQL in Python kami.

Transformasi Kolom dengan Fungsi Bawaan dan User-Defined Function

Sering kali Anda perlu memformat atau merestrukturisasi kolom, mengubah string menjadi huruf besar, membaginya menjadi bagian-bagian, menggabungkan nilai, dan sebagainya. PySpark memiliki pustaka fungsi bawaan yang kaya yang bekerja langsung di dalam withColumn().

Contohnya seperti ini:

from pyspark.sql.functions import upper, concat_ws, split
df = df.withColumn("full_caps", upper(col("name")))
df = df.withColumn("city_state", concat_ws(", ", col("city"), col("state")))
df = df.withColumn("first_word", split(col("description"), " ").getItem(0))

Fungsi bawaan itu hebat. Cepat, native, dan teroptimasi. Namun kadang, Anda punya aturan sekali pakai yang tidak pas di mana pun. Saat itulah user-defined function (UDF) berguna.

Menggunakan UDF

Misalnya Anda ingin menghitung panjang string dan memberi label:

from pyspark.sql.functions import udf
from pyspark.sql.types import StringType
def label_length(x):
    return "short" if len(x) < 5 else "long"
label_udf = udf(label_length, StringType())
df = df.withColumn("name_length_label", label_udf(col("name")))

Cukup sederhana. Namun tetap hati-hati, UDF memiliki overhead. Mereka menarik data keluar dari mesin yang teroptimasi, menjalankannya di Python, lalu membungkusnya kembali. Itu tidak masalah saat dibutuhkan, tetapi untuk tugas ber-volume tinggi, utamakan fungsi bawaan atau ekspresi SQL jika memungkinkan.

Pelajari cara membuat, mengoptimalkan, dan menggunakan PySpark UDF, termasuk Pandas UDF, untuk menangani transformasi data kustom secara efisien dan meningkatkan kinerja Spark dari tutorial How to Use PySpark UDFs and Pandas UDFs Effectively kami.

Pertimbangan Kinerja dan Praktik Lanjutan

Pada titik tertentu, setiap pengguna PySpark mengalami ini: Anda terus menumpuk pemanggilan withColumn() dan pipeline Anda melambat drastis. Alasannya? Setiap pemanggilan menambah lapisan baru pada rencana logis, yang harus diurai, dioptimalkan, dan dieksekusi oleh Spark.

Jika Anda hanya menambahkan satu atau dua kolom, tidak masalah. Namun jika Anda merangkai lima, enam, atau lebih, Anda perlu mulai berpikir berbeda.

Gunakan select() saat menambah banyak kolom

Alih-alih memanggil withColumn() berulang kali, bangun daftar kolom baru menggunakan select():

df = df.select(
    "*",
    (col("salary") * 0.1).alias("bonus"),
    (col("age") + 5).alias("age_plus_five")
)

Pendekatan ini membangun rencana logis sekaligus.

Pelajari lebih lanjut tentang select() dan metode lain di tutorial PySpark Cheat Sheet: Spark in Python kami.

Bagaimana dengan withColumns()?

Diperkenalkan di Spark 3.3, withColumns() memungkinkan Anda menambahkan beberapa kolom dalam satu kali proses. Tidak perlu pemanggilan berulang. Metodenya bergaya kamus:

df = df.withColumns({
    "bonus": col("salary") * 0.1,
    "age_plus_five": col("age") + 5
})

Tidak semua orang sudah menggunakan Spark 3.3+ saat ini, tetapi jika Anda sudah, gunakan ini. Lebih bersih, lebih cepat, dan menghindari masalah “mati karena chaining”.

Contoh Lengkap PySpark withColumn() Langkah demi Langkah

Misalkan Anda mengerjakan data aktivitas pengguna untuk platform berbasis langganan. DataFrame mentah Anda terlihat seperti ini:

from pyspark.sql import SparkSession
spark = SparkSession.builder.appName("withColumn-demo").getOrCreate()
data = [
    ("Alice", "NY", 24, 129.99),
    ("Bob", "CA", 31, 199.95),
    ("Charlie", "TX", 45, 0.0),
    ("Diana", "WA", 17, 19.99)
]
columns = ["name", "state", "age", "purchase_amount"]
df = spark.createDataFrame(data, columns)

Anda memiliki nama, negara bagian, usia, dan berapa banyak yang mereka belanjakan. Cukup dasar. Namun di dunia nyata, itu tidak pernah cukup. Jadi berikut yang akan kita lakukan selanjutnya:

  • Menambahkan kolom konstan untuk tanggal ingest.
  • Membuat kolom baru yang menunjukkan apakah pengguna dewasa.
  • Memformat purchase_amount menjadi dua tempat desimal.
  • Mengategorikan pengguna berdasarkan tingkat belanja.
  • Menerapkan fungsi kustom untuk memberi label pada pengguna.
  • Menggunakan withColumns() untuk merangkum nilai tambahan dengan cara yang lebih rapi.

Sedang bersiap untuk wawancara berikutnya? Artikel Top 36 PySpark Interview Questions and Answers for 2025 menyediakan panduan komprehensif pertanyaan dan jawaban wawancara PySpark, mencakup topik dari konsep dasar hingga teknik lanjutan dan strategi optimasi.

Langkah 1: Tambahkan tanggal ingest konstan

Sebaiknya melacak kapan data dimasukkan ke dalam sistem Anda.

from pyspark.sql.functions import lit
df = df.withColumn("ingest_date", lit("2025-07-29"))

Langkah 2: Tandai dewasa vs. anak di bawah umur

Anda bisa saja menggunakan col("age") >= 18, tetapi membungkusnya dengan when() memberi Anda kendali penuh jika logikanya makin rumit.

from pyspark.sql.functions import when, col
df = df.withColumn(
    "is_adult",
    when(col("age") >= 18, True).otherwise(False)
)

Langkah 3: Format purchase_amount

Mengubah tipe adalah salah satu pekerjaan pembersihan yang paling sering Anda lakukan, terutama saat membaca dari CSV atau JSON.

df = df.withColumn("purchase_amount", col("purchase_amount").cast("decimal(10,2)"))

Langkah 4: Kategorikan tingkat belanja

Misalkan Anda ingin tiga grup: “none”, “low”, dan “high”.

df = df.withColumn(
    "spend_category",
    when(col("purchase_amount") == 0, "none")
    .when(col("purchase_amount") < 100, "low")
    .otherwise("high")
)

Ini membantu Anda melakukan segmentasi pengguna tanpa menjalankan query terpisah.

Langkah 5: Beri label pengguna menggunakan UDF

Sekarang aturan rekaan. Misalkan Anda memberi label seseorang berdasarkan panjang namanya.

from pyspark.sql.functions import udf
from pyspark.sql.types import StringType
def user_label(name):
    return "simple" if len(name) <= 4 else "complex"
label_udf = udf(user_label, StringType())
df = df.withColumn("label", label_udf(col("name")))

Langkah 6: Tambahkan beberapa kolom ekstra sekaligus

Mungkin Anda ingin beberapa lagi, usia dalam bulan, dan pesan sambutan.

df = df.withColumns({
    "age_in_months": col("age") * 12,
    "welcome_msg": col("name") + lit(", welcome aboard!")
})

Jauh lebih rapi daripada memanggil withColumn() dua kali.

Berikut tampilan akhir DataFrame saat Anda menampilkannya:

df.show(truncate=False)

name

state

age

purchase_amount

ingest_date

is_adult

spend_category

label

age_in_months

welcome_msg

Alice

NY

24

129.99

2025-07-29

True

high

complex

288

Alice, welcome aboard!

Bob

CA

31

199.95

2025-07-29

True

high

simple

372

Bob, welcome aboard!

Charlie

TX

45

0.00

2025-07-29

True

none

complex

540

Charlie, welcome aboard!

Diana

WA

17

19.99

2025-07-29

False

low

complex

204

Diana, welcome aboard!

Tumpukan transformasi seperti ini umum dalam rekayasa fitur, pelaporan, atau merapikan feed pihak ketiga.

Pelajari dasar-dasar bekerja dengan big data menggunakan PySpark dari kursus Big Data Fundamentals with PySpark kami.

Praktik Terbaik dan Jebakan withColumn()

withColumn() milik PySpark mungkin terlihat sederhana, tetapi bisa menjerumuskan bahkan engineer berpengalaman jika Anda tidak berhati-hati. Berikut hal-hal yang diam-diam bisa merusak pipeline Anda, beserta beberapa kebiasaan yang dapat menyelamatkan Anda dari kejutan tidak menyenangkan.

Selalu tetapkan ulang hasilnya

Ini dasar, tetapi masih sering mengecoh: withColumn() tidak memodifikasi DataFrame asli Anda. Ia memberi Anda yang baru. Jika Anda lupa menetapkannya ulang, perubahan Anda hilang.

df.withColumn("new_col", lit(1))  # Ini tidak akan melakukan apa pun
df = df.withColumn("new_col", lit(1))  # Ini berfungsi

Waspadai overwrite tidak sengaja

Misalkan DataFrame Anda memiliki kolom bernama status. Anda menjalankan ini:

df = df.withColumn("Status", lit("Active"))

Terlihat tidak berbahaya, bukan? Namun Spark memperlakukan nama kolom sebagai tidak peka huruf besar/kecil secara default. Artinya Anda baru saja menimpa kolom status asli. Tanpa menyadarinya.

Salah satu solusinya adalah selalu memeriksa df.columns sebelum dan sesudah. Atau, jika pipeline Anda mendukung, aktifkan kepekaan huruf besar/kecil menggunakan:

spark.conf.set("spark.sql.caseSensitive", "true")

Jangan gunakan literal Python dalam ekspresi

Yang satu ini mudah terlupa. Saat menambahkan konstanta, hindari nilai Python mentah. Selalu bungkus dengan lit().

df = df.withColumn("region", "US")  # Buruk
df = df.withColumn("region", lit("US"))  # Baik

Mengapa? Karena withColumn() mengharapkan ekspresi Column, bukan nilai mentah. Jika Anda keliru, Spark bisa melempar error yang tidak membantu, atau lebih buruk, diam-diam merusak logika hilir.

Tangani pengecualian di luar withColumn()

Terkadang orang menjadi kreatif dan membungkus seluruh blok withColumn() di dalam try/except. Lebih baik mengisolasi bagian yang berisiko (seperti UDF atau pembacaan data) dan menangkap pengecualiannya di sana. Jaga lapisan transformasi Anda tetap bersih dan dapat diprediksi.

try:
    def risky_udf(x):
        if not x:
            raise ValueError("Empty input")
        return x.lower()
except Exception as e:
    print("Error in UDF definition:", e)

Biarkan Spark gagal lebih awal, jangan sembunyikan di balik try block bersarang.

Pelajari lebih lanjut tentang pengecualian di Python dari tutorial Exception & Error Handling in Python kami.

Utamakan fungsi bawaan daripada UDF

Memang, UDF memberi Anda kekuatan. Namun ada trade-off: kinerja lebih lambat, debugging lebih sulit, dan optimasi lebih sedikit. Jika ada fungsi bawaan yang bisa melakukan tugasnya, gunakan itu.

Yang ini:

df = df.withColumn("upper_name", upper(col("name")))

Jauh lebih cepat daripada ini:

df = df.withColumn("upper_name", udf(lambda x: x.upper(), StringType())(col("name")))

Kapan Tidak Menggunakan withColumn()

Terlepas dari fleksibilitas withColumn(), ada saat-saat ketika ini bukan alat yang tepat.

Anda merombak banyak kolom sekaligus

Jika Anda mendapati diri memanggil withColumn() 10 kali berturut-turut, saatnya beralih. Gunakan select() sebagai gantinya dan tulis transformasi Anda sebagai bagian dari proyeksi baru.

df = df.select(
    col("name"),
    col("age"),
    (col("salary") * 0.15).alias("bonus"),
    (col("score") + 10).alias("adjusted_score")
)

Lebih jelas, kinerjanya lebih baik, dan membuat optimizer Spark bekerja untuk Anda, bukan melawan Anda.

Anda ingin menulis logika bergaya SQL

Jika tim Anda sangat mengandalkan SQL, dan Anda sudah mendaftarkan DataFrame sebagai tampilan sementara, sering kali lebih bersih untuk langsung menjalankan query SQL.

df.createOrReplaceTempView("users")
df2 = spark.sql("""
    SELECT name, age,
           CASE WHEN age >= 18 THEN true ELSE false END AS is_adult
    FROM users
""")

Ini bisa lebih mudah bagi analis yang mahir SQL atau tim yang bekerja lintas Spark dan database tradisional.

Bangun keterampilan SQL Anda dengan kursus, track, dan proyek interaktif yang dikurasi oleh pakar dunia nyata melalui SQL Courses kami.

Anda sudah menggunakan Spark 3.3+

Jika Anda menggunakan Spark 3.3 atau yang lebih baru dan perlu menambahkan banyak kolom, withColumns() adalah teman Anda. Ini bukan hanya praktis, tetapi bisa lebih cepat di balik layar dengan membuat satu pembaruan rencana logis.

Pelajari cara menerapkan manajemen data terdistribusi dan machine learning di Spark menggunakan paket PySpark dari kursus Foundations of PySpark kami.

Kesimpulan

Fungsi withColumn() PySpark adalah salah satu alat paling serbaguna dalam gudang transformasi data Anda, memberi kemampuan untuk menambah, memodifikasi, dan merekayasa fitur langsung dalam alur kerja berpusat pada DataFrame. Dari casting tipe dan menyisipkan konstanta hingga menyematkan logika kompleks dengan kondisional dan UDF, withColumn() membantu Anda membentuk data yang berantakan menjadi pipeline siap produksi.

Namun bersama kekuatan itu ada tanggung jawab. Penggunaan berlebihan withColumn() dalam rantai panjang dapat diam-diam menurunkan kinerja dengan membengkakkan rencana logis, membuat job Spark Anda lebih sulit dioptimalkan dan di-debug. Itulah mengapa mengetahui kapan harus menggunakan select(), withColumns(), atau bahkan SQL dapat menjadi pembeda antara job yang tersendat dan yang skalabel.

Dengan Spark yang terus berkembang, terutama dengan fitur seperti withColumns() di Spark 3.3+, memahami internal dan trade-off kinerja dari setiap metode adalah kunci untuk menulis kode yang lebih bersih, lebih cepat, dan lebih mudah dirawat.

Kuasai teknik di balik transformasi kolom skala besar, hindari jebakan pembengkakan rencana, dan pelajari bagaimana para profesional merampingkan pipeline fitur di kursus Feature Engineering with PySpark kami.

PySpark withColumn() FAQs

Why is my Spark job slow when I use withColumn() a lot?

Saat Anda merangkai beberapa pemanggilan withColumn(), Spark menambahkan masing-masing sebagai langkah terpisah dalam rencana eksekusi logis. Lama-kelamaan, ini bisa berubah menjadi rencana yang membengkak, lebih sulit dioptimalkan dan lebih lambat dijalankan. Alih-alih menumpuk sepuluh pemanggilan withColumn(), cobalah membangun kolom baru di dalam satu select() atau gunakan withColumns() untuk menambahkan beberapa kolom sekaligus.

Can I use withColumn() to remove a column?

Tidak, withColumn() hanya menambah atau mengganti kolom, bukan menghapusnya. Jika Anda ingin menghapus kolom, gunakan drop(). Anda juga bisa menggunakan select() untuk menyimpan hanya kolom yang Anda butuhkan.

Why do I get an error when I try to use a string or number in withColumn()?

Itu biasanya terjadi saat Anda memasukkan nilai Python mentah alih-alih membungkusnya dengan lit(). withColumn() mengharapkan sebuah ekspresi Kolom Spark. Begini cara yang benar:

from pyspark.sql.functions import lit
df = df.withColumn("new_col", lit(42))  
Derrick Mwiti

Penulis

Derrick Mwiti

Topik

Terkait

blogs

Tutorial Korelasi di R

blogs

Spaghetti Plot dan Jalur Badai

blogs

40 Pertanyaan Wawancara DBMS Teratas di 2026