Indonesian (Bahasa Indonesia) translation by Agus Kurniawan (you can also view the original English article)
Ikhtisar
Salah satu aspek yang paling penting dari aplikasi apapun adalah memvalidasi inputny. Pendekatan yang paling dasar hanya gagal jika input tidak memenuhi persyaratan. Namun, dalam banyak kasus hal ini tidak cukup. Dalam banyak sistem, pengumpulan data terpisah dari analisis data. Ini bisa berupa sebuah survei atau kumpulan data lama.
Dalam kasus ini, Anda perlu memeriksa seluruh dataset sebelum analisis, mendeteksi data yang tidak valid atau hilang, memperbaiki apa yang dapat diperbaiki, dan menandai atau menghapus data yang tidak dapat diselamatkan. Hal ini juga berguna untuk menyediakan statistik tentang kualitas data dan jenis kesalahan apa yang muncul.
Dalam dua bagian seri ini Anda akan belajar bagaimana menggunakan fasilitas teks Go's, mengiris dan memotong file CSV, dan memastikan data Anda sangat bersih. Pada bagian satu, kita akan fokus pada dasar pengolahan teks di Go-byte, Rune dan string — serta bekerja dengan file CSV.
Text in Go
Sebelum kita melakukan pembersihan data, mari kita mulai dengan dasar teks di Go. Blok bangunan adalah byte, Rune, dan string. Mari kita lihat apa yang mewakili masing-masing dan apa hubungan antara mereka.
Byte
Byte adalah angka 8-bit. Setiap byte dapat mewakili salah satu dari kemungkinan 256 nilai (2 pangkat 8). Setiap karakter dalam set karakter ASCII dapat diwakili oleh satu byte. Tetapi byte tidak karakter. Alasannya adalah bahwa Go sebagai bahasa modern mendukung Unicode, dimana ada lebih dari 256 karakter yang berbeda. Masukkan rune.
Rune
Rune di GO adalah nama lain untuk jenis int32. Ini berarti bahwa setiap rune dapat mewakili lebih dari empat miliar nilai terpisah (2 pangkat 32), yang cukup baik untuk mencakup seluruh rangkaian karakter Unicode.
Dalam kode berikut Anda dapat melihat bahwa rune '∆' (alt-J pada Mac) hanyalah sebuah int32. Untuk mencetak karakter ini mewakili ke layar, saya harus mengubahnya menjadi string.
package main import ( "fmt" ) func main() { r := '∆' fmt.Println(r) fmt.Println(int32(r)) fmt.Println(string(r)) } Output: 8710 8710 ∆
Unicode rumit. Rune secara resmi mewakili titik kode Unicode. Karakter Unicode biasanya diwakili oleh satu titik kode Unicode, tapi kadang-kadang lebih dari satu.
String
String secara resmi hanya berupa irisan byte saja. Jika Anda mengindeks string, Anda mendapatkan byte kembali:
func main() { s := "abc" for i := 0; i < len(s); i++ { fmt.Println(s[i]) } } Output: 97 98 99
Literal String adalah urutan karakter UTF-8 yang disertakan dalam tanda kutip ganda. Mereka mungkin berisi urutan escape, yang merupakan garis miring terbalik yang diikuti oleh karakter ASCII seperti \n (newline) atau \t (tab). Mereka memiliki arti khusus. Berikut adalah daftar lengkap:
\a U+0007 alert or bell \b U+0008 backspace \f U+000C form feed \n U+000A line feed or newline \r U+000D carriage return \t U+0009 horizontal tab \v U+000b vertical tab \\ U+005c backslash \' U+0027 single quote (valid only within rune literals) \" U+0022 double quote (valid only within string literals)
Kadang-kadang Anda mungkin ingin menyimpan byte literal secara langsung dalam string, terlepas dari urutan escape, Anda dapat melarikan diri setiap tanda garis miring terbalik, tapi itu membosankan. Banyak pendekatan yang lebih baik adalah dengan menggunakan string mentah yang diapit oleh backticks.
Berikut adalah contoh dari string dengan urutan escape \t (tab), yang dipresentasikan sekali apa adanya, kemudian melarikan diri tanda garis miring terbalik dan kemudian sebagai string mentah:
func main() { s1 := "1\t2" s2 := "1\\t2" s3 := `1\t2` fmt.Println(s1) fmt.Println(s2) fmt.Println(s3) } Output: 1 2 1\t2 1\t2
Sementara string adalah irisan byte, , Anda mendapatkan rune dalam setiap iterasi. Ini berarti Anda bisa mendapatkan satu atau lebih byte. Hal ini mudah untuk melihat dengan indeks untuk rentang. Berikut adalah contoh gila. Kata Ibrani "שלום" berarti "Halo" (dan perdamaian). Bahasa Ibrani juga ditulis dari kanan ke kiri. Saya akan membuat sebuah string yang mencampurkan perkataan Ibrani dengan terjemahan dalam bahasa Inggris.
Kemudian, saya akan mencetaknya rune by rune, termasuk indeks byte dari setiap rune dalam string. Seperti yang Anda lihat,setiap rune bahasa Ibrani membawa dua byte, sementara karakter bahasa Inggris mengambil satu byte, sehingga total panjang string ini adalah 16 byte, meskipun memiliki empat karakter Ibran tiga simbol dan lima karakter bahasa Inggris (12 karakter). Juga, karakter Ibrani akan ditampilkan dari kanan ke kiri:
func main() { hello := "שלום = hello" fmt.Println("length:", len(hello)) for i, r := range(hello) { fmt.Println(i, string(r)) } } Output: length: 16 0 ש 2 ל 4 ו 6 ם 8 9 = 10 11 h 12 e 13 l 14 l 15 o
Semua nuansa ini bisa sangat penting bila Anda memiliki dataset untuk membersihkan dengan kutipan aneh dan campuran karakter dan simbol Unicode.
Ketika mencetak string dan irisan byte, ada beberapa penentu format yang berfungsi sama pada kedua. Format %S mencetak byte seperti, %x mencetak dua karakter heksadesimal huruf kecil per byte, %X mencetak dua karakter heksadesimal huruf besar per byte, dan %q mencetak string dikutip ganda diloloskan dengan sintaks pergi.
Untuk menghindari tanda % di dalam penentu sting format,cukup gandakanl. Untuk memisahkan byte saat menggunakan %x atau %X, Anda dapat menambahkan spasi, seperti dalam "% x" dan "% X". Berikut ini adalah demo:
func main() { s := "שלום" fmt.Printf("%%s format: %s\n", s) fmt.Printf("%%x format: %x\n", s) fmt.Printf("%%X format: %X\n", s) fmt.Printf("%% x format: % x\n", s) fmt.Printf("%% X format: % X\n", s) fmt.Printf("%%q format: %q\n", s) } Output: %s format: שלום %x format: d7a9d79cd795d79d %X format: D7A9D79CD795D79D % x format: d7 a9 d7 9c d7 95 d7 9d % X format: D7 A9 D7 9C D7 95 D7 9D %q format: "שלום"
Membaca dan Menulis File CSV
Data dapat tiba dalam berbagai cara dan format. Salah satu format yang paling umum adalah CSV (comma separated values).Data CSV sangat efisien. File biasanya memiliki baris tajuk dengan nama bidang atau kolom dan baris data dimana setiap baris berisi nilai setiap bidang, dipisahkan dengan koma.
Berikut adalah sedikit potongan dari dataset penampakan UFO (benar). Baris pertama (header) berisi nama-nama kolom, dan baris lain berisi data. Anda dapat melihat bahwa sering kali kolom "Warna Dilaporkan" kosong:
City,Colors Reported,Shape Reported,State,Time Ithaca,,TRIANGLE,NY,6/1/1930 22:00 Willingboro,,OTHER,NJ,6/30/1930 20:00 Holyoke,,OVAL,CO,2/15/1931 14:00 Abilene,,DISK,KS,6/1/1931 13:00 New York Worlds Fair,,LIGHT,NY,4/18/1933 19:00 Valley City,,DISK,ND,9/15/1934 15:30 Crater Lake,,CIRCLE,CA,6/15/1935 0:00 Alma,,DISK,MI,7/15/1936 0:00 Eklutna,,CIGAR,AK,10/15/1936 17:00 Hubbard,,CYLINDER,OR,6/15/1937 0:00 Fontana,,LIGHT,CA,8/15/1937 21:00 Waterloo,,FIREBALL,AL,6/1/1939 20:00 Belton,RED,SPHERE,SC,6/30/1939 20:00
Menulis bagian data CSV ini ke file melibatkan beberapa operasi string serta bekerja dengan file. Sebelum kita masuk ke dalam logika utama, berikut adalah bagian-bagian wajib: definisi paket, impor dan data string (perhatikan penggunaan const).
package main import ( "os" "strings" "bufio" ) data := ` City,Colors Reported,Shape Reported,State,Time Ithaca,,TRIANGLE,NY,6/1/1930 22:00 Willingboro,,OTHER,NJ,6/30/1930 20:00 Holyoke,,OVAL,CO,2/15/1931 14:00 Abilene,,DISK,KS,6/1/1931 13:00 New York Worlds Fair,,LIGHT,NY,4/18/1933 19:00 Valley City,,DISK,ND,9/15/1934 15:30 Crater Lake,,CIRCLE,CA,6/15/1935 0:00 Alma,,DISK,MI,7/15/1936 0:00 Eklutna,,CIGAR,AK,10/15/1936 17:00 Hubbard,,CYLINDER,OR,6/15/1937 0:00 Fontana,,LIGHT,CA,8/15/1937 21:00 Waterloo,,FIREBALL,AL,6/1/1939 20:00 Belton,RED,SPHERE,SC,6/30/1939 20:00 `
Fungsi utama() membuat sebuah file bernama "ufo-sightings.csv", memeriksa bahwa tidak ada kesalahan, dan kemudian membuat penulis buffered w. Menunda panggilan di baris berikutnya, yang flushes isi buffer ke file, dijalankan pada akhir fungsi. Itulah makna menunda. Kemudian, ia menggunakan fungsi Split() dari paket string untuk memecah string data dalam setiap baris.
Kemudian, di dalam for-loop, spasi putih terkemuka dan tertinggal dipangkas dari setiap baris. Baris kosong diabaikan dan baris tidak kosong ditulis ke buffer, diikuti oleh karakter baris baru. Buffer akan memerah ke file dalam akhirnya.
func main() { f, err := os.Create("ufo-sightings.csv") if err != nil { panic(e) } w := bufio.NewWriter(f) defer w.Flush() lines := strings.Split(data, "\n") for _, line := range lines { line := strings.Trim(line, " ") if line == "" { continue } w.WriteString(line) w.WriteString("\n") } }
Membaca dari file ini cukup sederhana:
package main import ( "fmt" "io/ioutil" ) func main() { data, err := ioutil.ReadFile("ufo-sightings.csv") if err != nil { panic(err) } fmt.Println(string(data)) }
Kesimpulan
Go memiliki fasilitas yang kuat untuk menangani teks dari segala bentuk dan penyandian.. Di bagian seri ini, kita melihat ke dasar representasi teks Go, pemrosesan teks menggunakan paket string, dan berurusan dengan file CSV.
Dalam bagian kedua, kami akan menerapkan apa yang telah kami mpelajari dalam praktek untuk membersihkan data yang berantakan dalam persiapan untuk analisis.