Copy-on-Write adalah semantik memori pandas yang menjadikan setiap hasil seleksi sebagai salinan yang baru mengalokasikan datanya sendiri ketika ditulis, dan pada pandas 3.x semantik ini selalu aktif tanpa pengaturan tambahan. Topik ini memerinci konsekuensinya pada penugasan nilai, mulai dari salinan malas hasil seleksi kolom, pola penulisan dirangkai yang berakhir dengan peringatan, penulisan nilai yang benar melalui loc, hingga posisi metode copy() di aturan baru ini. Setelah membaca, penulisan nilai pada tabel tidak lagi bergantung pada efek samping yang tidak pernah terjadi.
Salinan malas pada hasil seleksi#
Series yang diambil melalui df["kolom"] bukan jendela langsung ke data DataFrame asalnya, melainkan salinan malas yang baru menyalin isinya ketika diubah. Salinan malas berbagi memori dengan asalnya selama belum tersentuh, sehingga pembuatannya murah, tetapi penugasan nilai pertama memicu penyalinan yang berdiri sendiri. Blok berikut menunjukkan konsekuensinya pada kolom suhu_c dataset kontrak.
import numpy as np
import pandas as pd
rng = np.random.default_rng(42)
n = 96
df = pd.DataFrame({
"waktu": pd.date_range("2026-01-05 07:00", periods=n, freq="15min"),
"ruang": rng.choice(["Lab A", "Lab B", "Ruang Arsip"], n, p=[0.4, 0.35, 0.25]),
"suhu_c": np.round(rng.normal(24, 1.5, n), 1),
"lembap_pct": np.round(rng.normal(60, 5, n), 1),
"status_sensor": rng.choice(["normal", "kalibrasi", "rusak"], n, p=[0.85, 0.10, 0.05]),
})
df.to_csv("sensor_log.csv", index=False) # dataset bersama untuk seluruh modul
df = pd.read_csv("sensor_log.csv", parse_dates=["waktu"])
s = df["suhu_c"]
s.iloc[0] = 99.0
print("df tetap:", df["suhu_c"].iloc[0])
print("s berubah:", s.iloc[0])df tetap: 21.5
s berubah: 99.0Penugasan s.iloc[0] = 99.0 sah dan tidak disambut peringatan apa pun, tetapi perubahannya berhenti pada s itu sendiri, sedangkan df tetap menampilkan 21.5 derajat pada baris pertamanya. Isolasi ini berlaku dua arah, karena perubahan pada df setelah seleksi juga tidak merambat ke s yang sudah dibuat. Tidak ada peringatan pada pola ini karena penugasannya sendiri benar, hanya asumsi bahwa perubahannya merambat yang keliru. Dengan begitu, pola apa pun yang mengandalkan perubahan lewat hasil seleksi tidak pernah bekerja pada pandas 3.x.
Chained assignment dan peringatannya#
Penulisan nilai melalui dua tahap seleksi yang dirangkai, yakni chained assignment, tidak pernah mengubah tabel asal pada pandas 3.x dan selalu disambut peringatan ChainedAssignmentError. Ekspresi df["suhu_c"][0] = 99.0 terdiri atas dua langkah yang dijalankan berurutan, yaitu pengambilan kolom yang menghasilkan salinan, lalu penugasan pada salinan itu. Peringatannya berupa warning, bukan exception yang menghentikan program, sehingga perlu ditangkap untuk diperiksa.
import warnings
import pandas as pd
df = pd.read_csv("sensor_log.csv", parse_dates=["waktu"])
with warnings.catch_warnings(record=True) as terekam:
warnings.simplefilter("always")
df["suhu_c"][0] = 99.0
print("df tetap:", df["suhu_c"].iloc[0])
print("jenis peringatan:", terekam[0].category.__name__)
print(str(terekam[0].message).splitlines()[0])df tetap: 21.5
jenis peringatan: ChainedAssignmentError
A value is being set on a copy of a DataFrame or Series through chained assignment.Nilai 99.0 tidak pernah sampai ke tabel karena yang ditulis adalah salinan sementara hasil langkah pertama, dan peringatan ChainedAssignmentError menyatakan persis hal itu. Pesannya bahkan menyarankan bentuk penulisan yang benar, dan pada topik Seleksi dengan loc pola yang sama sudah diperlihatkan pada kasus seleksi ber-mask. Keluaran yang tercetak tetap bersih karena peringatan itu ditangkap melalui warnings.catch_warnings(record=True), sesuai kebiasaan seluruh topik di jalur ini.
Penulisan nilai yang benar#
Nilai ditulis langsung pada objek DataFrame yang dirujuk, baik melalui df.loc[mask, "kolom"] = nilai untuk baris terpilih maupun df["kolom"] = nilai untuk satu kolom penuh. Kedua bentuk menyasar tabel secara eksplisit dalam satu ekspresi, sehingga tidak ada salinan sementara yang menjadi sasaran penugasan. Blok berikut menerapkan keduanya pada dataset kontrak.
import numpy as np
import pandas as pd
df = pd.read_csv("sensor_log.csv", parse_dates=["waktu"])
mask = df["status_sensor"] == "rusak"
df.loc[mask, "suhu_c"] = np.nan
df["selisih_lembap"] = (df["lembap_pct"] - 55).round(1)
print(df.loc[mask, ["ruang", "suhu_c", "status_sensor"]])
print(df[["lembap_pct", "selisih_lembap"]].head(3)) ruang suhu_c status_sensor
43 Lab A NaN rusak
87 Lab B NaN rusak
89 Lab B NaN rusak
lembap_pct selisih_lembap
0 68.6 13.6
1 59.1 4.1
2 58.1 3.1Tiga baris berstatus rusak pada indeks 43, 87, dan 89 kini bertanda NaN pada kolom suhu_c, dan perubahan itu benar-benar tersimpan pada tabel. Penugasan df["selisih_lembap"] = ... membuat kolom baru yang isinya dihitung dari seluruh baris sekaligus tanpa perulangan. Kedua bentuk berjalan tanpa peringatan karena objek sasarannya tidak ambigu, dan kebiasaan inilah yang membuat kode penulisan nilai tidak perlu memanggil copy(). Gunakan bentuk loc setiap kali sasarannya baris tertentu, dan bentuk satu kolom ketika seluruh kolom ikut diganti.
Kapan copy() diperlukan#
Metode copy() bukan lagi alat pengaman tabel asal, melainkan pernyataan maksud bahwa salinan bebas memang dikehendaki. Salinan bebas mengalokasikan datanya seketika dan terisolasi dua arah sejak awal, berbeda dari salinan malas yang menyalinnya hanya ketika ditulis. Blok berikut memperlihatkan isolasi penuh itu.
import pandas as pd
df = pd.read_csv("sensor_log.csv", parse_dates=["waktu"])
salin = df["suhu_c"].copy()
salin.iloc[0] = 40.0
df.loc[0, "suhu_c"] = 30.0
print("df:", df["suhu_c"].iloc[0])
print("salin:", salin.iloc[0])df: 30.0
salin: 40.0Kedua objek kini memuat nilai yang berbeda tanpa saling mengganggu, dan hasil yang sama sebenarnya diperoleh tanpa copy() karena salinan malas pun terisolasi. Memanggil copy() di mana-mana hanya menambah pekerjaan penyalinan tanpa mengubah perilakunya. Gunakan copy() ketika deret akan dimodifikasi lebih dahulu sebelum dipakai, atau ketika deret diteruskan ke fungsi lain yang boleh mengubah isinya tanpa memengaruhi tabel. Pada kasus-kasus itulah penyalinan seketika menyatakan maksud secara jelas.
Kesalahan umum#
Kesalahan yang tersisa adalah mengandalkan efek samping pada deret hasil seleksi, misalnya fungsi yang mengubah argumennya sambil mengharapkan tabel asal ikut berubah. Fungsi semacam itu menerima salinan hasil seleksi, sehingga mutasinya berhenti pada salinan itu dan tabel asalnya tidak pernah tersentuh.
import pandas as pd
def nolkan_bacaan_pertama(suhu):
suhu.iloc[0] = 0.0
return suhu
df = pd.read_csv("sensor_log.csv", parse_dates=["waktu"])
nolkan_bacaan_pertama(df["suhu_c"])
print("setelah pemanggilan biasa:", df["suhu_c"].iloc[0])
df["suhu_c"] = nolkan_bacaan_pertama(df["suhu_c"])
print("setelah penugasan kembali:", df["suhu_c"].iloc[0])setelah pemanggilan biasa: 21.5
setelah penugasan kembali: 0.0Pemanggilan pertama tidak menimbulkan error maupun peringatan, tetapi nilai pada df tetap 21.5 derajat karena fungsi mengubah salinan yang segera dibuang. Perbaikannya adalah fungsi yang mengembalikan Series hasil perubahannya, kemudian hasil itu ditugaskan kembali ke kolom seperti pada pemanggilan kedua yang menyimpan 0.0. Pola fungsi tanpa efek samping semacam ini sekaligus lebih mudah diuji, karena keluarannya diperiksa langsung tanpa membaca tabel asalnya.
Ringkasan#
s = df["kolom"]menghasilkan salinan malas, sehingga pengubahan padastidak pernah merambat kedf, dan arah sebaliknya pun tidak.- Pola dirangkai seperti
df["kolom"][0] = 99memunculkan peringatanChainedAssignmentErrordan nilainya tidak diterapkan pada tabel. - Penulisan yang sah adalah
df.loc[mask, "kolom"] = nilaiuntuk baris terpilih dandf["kolom"] = nilaiuntuk satu kolom penuh. copy()dipakai hanya ketika salinan bebas memang dikehendaki, bukan untuk mengamankan tabel asal.
Referensi#
- Copy-on-Write (CoW) — pandas User Guide — penjelasan resmi semantik salinan ketika ditulis beserta dampaknya pada penugasan.
- Indexing and selecting data — pandas User Guide
— bab resmi seleksi dan penulisan nilai melalui
locbeserta aturan chained assignment. - Migration Guides — pandas User Guide
— daftar perubahan pandas 3, termasuk berakhirnya era
SettingWithCopyWarning.