Data nyata jarang sebatas angka. Nama pelanggan, kode produk, dan kategori barang semuanya berupa teks. NumPy menyediakan dua jalur untuk menyimpan teks di dalam array: dtype Unicode berlebar tetap (<U...) yang efisien tetapi kaku, dan dtype object yang fleksibel tetapi membatalkan banyak keunggulan kecepatan NumPy. Bab ini membahas keduanya beserta batas-batasnya, supaya kita tahu kapan sebaiknya teks dikerjakan di luar NumPy.

dtype <U: Unicode Berlebar Tetap #

Ketika array dibuat dari list string, NumPy memeriksa string terpanjang lalu menetapkan lebar tetap untuk seluruh elemen. Nama dtype-nya berupa <U<n>, misalnya <U4 berarti setiap sel menyimpan maksimal 4 karakter Unicode. Karena setiap karakter Unicode dipakai 4 byte (UCS-4), itemsize array bertipe <U4 adalah 16 byte per elemen, sekecil apa pun isi stringnya.

python
import numpy as np

nama = np.array(["Budi", "Siti", "Dewi"])
print(nama.dtype)
print(nama.itemsize)

kata = np.array(["satu", "dua"])
print(kata.dtype)

Output yang Dihasilkan:

text
<U4
16
<U4

Bedah baris per baris:

  1. Baris 3 (np.array(["Budi", "Siti", "Dewi"])): string terpanjang adalah "Budi" dengan 4 karakter, sehingga NumPy menetapkan dtype <U4 untuk seluruh elemen.
  2. Baris 5 (nama.itemsize): hasilnya 16, yaitu 4 karakter dikali 4 byte per karakter. Elemen "Siti" tetap menghabiskan 16 byte meskipun isinya hanya 4 karakter termasuk ruang kosong sisa.
  3. Baris 8 (np.array(["satu", "dua"])): string terpanjang "satu" juga 4 karakter, sehingga dtype-nya <U4; lebar ditentukan otomatis dari data terpanjang, bukan dari tipe data semula.

Konsekuensi lebar tetap ini muncul ketika kita memaksakan lebar yang lebih kecil daripada string aslinya.

Truncation: String Terpotong Tanpa Suara #

Jika dtype ditentukan manual dengan lebar yang tidak cukup, NumPy memotong (truncate) kelebihan karakter. Pemotongan ini terjadi diam-diam, baik saat array dibuat maupun saat elemen baru diisikan.

python
import numpy as np

kata = np.array(["satu", "dua"], dtype="U3")
print(kata)
print(kata.dtype)

label = np.array(["dua"], dtype="U3")
label[0] = "enam"
print(label)

Output yang Dihasilkan:

text
['sat' 'dua']
<U3
['ena']

Interpretasi hasil yang cukup mengejutkan:

  1. Baris 3 (dtype="U3"): "satu" (4 karakter) terpotong menjadi "sat", sementara "dua" (3 karakter) tetap utuh. Tidak ada error, tidak ada peringatan.
  2. Baris 7 (label[0] = "enam"): pengisian elemen dengan string 4 karakter ke array <U3 juga berakhir terpotong menjadi "ena", tanpa peringatan apa pun pada NumPy 2.x.

dtype Object: Python di Dalam Array #

dtype object tidak menyimpan data secara seragam; setiap sel menyimpan pointer ke objek Python bebas. Karena itu satu array object boleh berisi integer, string, dan float sekaligus. Kebebasan ini dibayar mahal: operasi elemen per elemen harus keluar dari C dan memanggil objek Python satu per satu, sehingga vectorization kehilangan maknanya.

python
import numpy as np

campur = np.array([1, "dua", 3.5], dtype=object)
print(campur.dtype)
print(campur)

teks = np.array(["ab", "cd"], dtype=object)
print(teks * 2)

u = np.array(["ab", "cd"])
try:
    u * 2
except TypeError as e:
    print("TypeError:", e)

Output yang Dihasilkan:

text
object
[1 'dua' 3.5]
['abab' 'cdcd']
TypeError: The 'out' kwarg is necessary. Use numpy.strings.multiply without it.

Penjelasan singkat:

  1. Baris 3 (dtype=object): tanpa argumen ini, NumPy menganggap seluruh list sebagai kumpulan string dan mengubah angka menjadi teks (kita akan mendapat ['1' 'dua' '3.5'] bertipe <U32); dtype=object menyuruh NumPy menyimpan pointer ke objek Python aslinya.
  2. Baris 5 (print(campur)): hasil cetak memakai format Python ('dua' dengan kutip) karena elemen-elemennya memang objek Python, bukan data homogen.
  3. Baris 8 (teks * 2): perkalian diteruskan ke operator * milik masing-masing objek Python, sehingga string terulang menjadi "abab" dan "cdcd".
  4. Baris 11-15 (u * 2): pada array bertipe <U, operator * tidak didefinisikan di NumPy 2.x dan memunculkan TypeError. Operasi string untuk array <U disediakan lewat modul np.strings, misalnya np.strings.multiply(u, 2).

Kapan Memakai yang Mana #

Aturan praktis yang bisa kita ikuti:

  • Teks berformat tetap (kode produk, nomor seri): dtype <U aman dan hemat, asalkan lebar dicermati.
  • Teks variatif atau analisis teks: kerjakan di Python murni atau pandas; keduanya punya tipe string yang lebih praktis diatur.
  • Kolom campuran tipe sebagai tahap antara: dtype=object boleh dipakai sesaat, lalu segera dikonversi ke tipe homogen.
  • Perhitungan angka: hindari string dan object sepenuhnya; konversi dulu ke tipe numerik seperti pada Chapter Konversi Tipe Data.