Advertisement
  1. Code
  2. Go

Paglilinis ng iyong Data Gamit ang Go: Bahagi 1

Scroll to top
Read Time: 9 min
This post is part of a series called Cleaning Up Your Data With Go.
Cleaning Up Your Data With Go: Part 2

Tagalog (Wikang Tagalog) translation by Robert Alexander (you can also view the original English article)

Pangkalahatang-ideya

Ang isa sa mga pinakamahalagang aspeto ng anumang aplikasyon ay pagpapatuloy sa pag-andar nito. Ang pinakasimpleng paraan lamang ay hindi gumagana kung ang input ay hindi naka-ayon sa mga kinakailangan. Ganoon pa man, sa maraming kaso ito ay hindi sapat. Sa maraming mga sistema ang koleksyon ng mga datos ay hiwalay sa pagsasa-ayos ng mga datos. Maaaring ito ay isang survey o isang lumang dataset.

Sa mga kasong ito, kinakailangan upang mapunta ang buong dataset bago pag-aralan, alamin ang mga hindi tama o nawawalang datos, ayusin kung ano ang maayos, at i-flag o tanggalin ang mga datos na hindi maaaring makuha. Kapaki-pakinabang din na magbigay ng mga istatistika tungkol sa kalidad ng nga datos at kung anong mga uri ng mga pagkakamali ang nakita.

Sa serye na ito sa dalawang bahagi, matututunan mo kung paano gamitin ang mga kagamitan ng teksto, slice at dice ng CSV ng Go, at tiyaking malinis ang iyong mga datos. Sa isang bahagi, tayo ay magbibigay pansin sa pundasyon ng pagpoproseso ng teksto sa Goóbytes, runes, at stringsó para na rin sa pagtatrabaho sa mga datos na CSV.

Teksto sa Go

Bago tayo magpunta sa paglilinis ng mga datos, magsimula tayo sa pundasyon ng teksto sa Go. Ang mga bloke ng gusali ay mga byte, rune, at mga string. Tingnan natin kung ano ang kinakatawan ng bawat isa at kung ano ang mga relasyon sa pagitan nila.

Bytes

Ang mga byte ay 8-bit na mga numero. Ang bawat byte ay maaaring nanganga-hulugan sa isa sa isang posibleng 256 na halaga (2 sa kapangyarihan ng 8). Ang bawat karakter sa ASCII karakter set ay maaaring kinakatawan ng isang byte. Ngunit ang mga byte ay hindi mga karaktrer. Ang dahilan dito ay ang Go bilang isang modernong wika ay sumusuporta sa Unicode, kung saan may paraan higit sa 256 magkakahiwalay na mga karakter. Magpasok ng runes.

Runes

Ang isang rune sa Go ay isa pang pangalan para sa uri ng int32. Nangangahulugan ito na ang bawat rune ay maaaring kumatawan sa higit sa apat na bilyong magkakahiwalay na halaga (2 sa lakas ng 32), na sapat na mabuti upang masakop ang buong hanay ng Unicode na karakter.

Sa sumusunod na mga koda maaari mong makita na ang rune '∆' (alt-J sa Mac) ay isang int32 lamang. Upang i-print ang character na kinakatawan nito sa screen, kailangan ko itong palitan sa isang string.

1
package main
2
3
import (
4
    "fmt"
5
)
6
7
8
func main() {
9
    r := '∆'
10
    fmt.Println(r)
11
    fmt.Println(int32(r))
12
    fmt.Println(string(r))
13
}
14
15
Output:
16
17
8710
18
8710
19

Kumplikado ang Unicode. Ang isang rune ay opisyal na kumakatawan sa isang Unicode na koda point. Ang unicode na karakter ay karaniwang kinakatawan ng isang solong titik Unicode na koda, ngunit kung minsan higit sa isa.

Mga string

Ang mga string ay opisyal na lamang na read-only na mga bahagi ng mga byte. Kung ini-index mo ang isang string, makakakuha ka ng isang byte sa likuran:

1
func main() {
2
    s := "abc"
3
    for i := 0; i < len(s); i++ {
4
        fmt.Println(s[i])        
5
    }
6
}
7
8
Output:
9
10
97
11
98
12
99

Ang mga literal na string ay isang pagkakasunud-sunod ng mga karakter na UTF-8 na nakapaloob sa mga dobleng quote. Maaaring may mga magkakasunod na pagkukuhanan, na isang pang-likod na sinusundan ng isang ASCII na karakter tulad ng \n (newline) o \t (tab). Mayroon silang mga espesyal na kahulugan. Narito ang buong listahan:

1
\a   U+0007 alert or bell
2
\b   U+0008 backspace
3
\f   U+000C form feed
4
\n   U+000A line feed or newline
5
\r   U+000D carriage return
6
\t   U+0009 horizontal tab
7
\v   U+000b vertical tab
8
\\   U+005c backslash
9
\'   U+0027 single quote  (valid only within rune literals)
10
\"   U+0022 double quote  (valid only within string literals)

Minsan gusto mong itabi ang mga literal na byte nang direkta sa isang string, ano man ang mga pagkakasunod-sunod ng escape. Maaari kang makatakas sa bawat backslash, ngunit iyan ay nakakapagod. Mas mahusay na diskarte ay ang paggamit ng hilaw na mga string na nakapaloob sa mga backtick.

Narito ang isang halimbawa ng isang string na may isang pagtanggal ng \t (tab), na kinakatawan ng isang beses bilang pagkatapos ay may backslash pag-alis, at pagkatapos ay bilang isang raw string:

1
func main() {
2
    s1 := "1\t2"
3
    s2 := "1\\t2"
4
    s3 := `1\t2`
5
    
6
    fmt.Println(s1)
7
    fmt.Println(s2)
8
    fmt.Println(s3)
9
}
10
11
Output:
12
13
1    2
14
1\t2
15
1\t2

Habang ang mga string ay hiwa ng mga byte, kapag umulit ka sa isang string na may isang pahayag para sa hanay, nakakakuha ka ng rune sa bawat pag-ulit. Nangangahulugan ito na maaari kang makakuha ng isa o higit pang mga byte. Madali itong makita sa index para sa saklaw. Narito ang isang nakatutuwang halimbawa. Ang salitang Hebreo na "שלום" ay nangangahulugang "Hello" (at kapayapaan). Ang Hebreo ay nakasulat din sa kanan upang iwanan. Magtatayo ako ng string na nagsasama ng salitang Hebreo gamit ang Ingles na pagsasalin nito.

Pagkatapos, ipi-print ko ang rune na ito ng rune, kabilang ang index na byte ng bawat rune sa loob ng string. Tulad ng makikita mo, ang bawat Hebrew rune ay tumatagal ng dalawang byte, habang ang mga Ingles na karakter ay tumatagal ng isang byte, kaya ang kabuuang haba ng string na ito ay 16 bytes, kahit na mayroon itong apat na salitang Hebreo, tatlong simbolo, at limang Ingles na karakter (12 na karakter). Ganoon din, ang mga karakter na Hebreo ay ipapakita mula sa kanan papuntang kaliwa:

1
func main() {
2
    hello := "שלום = hello"
3
    fmt.Println("length:", len(hello))
4
    for i, r := range(hello) {
5
        fmt.Println(i, string(r))
6
    }
7
}
8
9
Output:
10
11
length: 16
12
0 ש
13
2 ל
14
4 ו
15
6 ם
16
8  
17
9 =
18
10  
19
11 h
20
12 e
21
13 l
22
14 l
23
15 o

Ang lahat ng mga pagkaka-iba ay maaaring maging lubhang mahalaga kapag mayroon kang isang dataset upang linisin ang mga kakaibang mga quote at isang halo ng Unicode na karakter at mga simbolo.

Kapag ang mga string ng pag-print at mga byte na hiwa, mayroong ilang mga format specifiers na gumagana na parehong pareho. Ang format ng %s ang mga byte bilang ay, %x prints dalawang lowercase hexadecimal na mga karakter bawat byte, %X prints dalawang uppercase hexadecimal character bawat byte, Ang %q ay nag-print ng isang double quoted string escaped na may go syntax.

Upang makatakas sa % sign sa loob ng isang tagatukoy ng string ng format, doblehine ito. Upang paghiwalayin ang mga byte kapag gumagamit ng %x o %X, maaari kang magdagdag ng puwang, tulad ng sa "% x" at "% X".

1
func main() {
2
    s := "שלום"
3
4
    fmt.Printf("%%s format:  %s\n", s)
5
    fmt.Printf("%%x format:  %x\n", s)
6
    fmt.Printf("%%X format:  %X\n", s)
7
    fmt.Printf("%% x format:  % x\n", s)
8
    fmt.Printf("%% X format:  % X\n", s)
9
    fmt.Printf("%%q format:  %q\n", s)
10
}
11
12
Output:
13
14
%s format:  שלום
15
%x format:  d7a9d79cd795d79d
16
%X format:  D7A9D79CD795D79D
17
% x format:  d7 a9 d7 9c d7 95 d7 9d
18
% X format:  D7 A9 D7 9C D7 95 D7 9D
19
%q format:  "שלום"

Pagbabasa at Pagsusulat ng Mga File ng CSV

Maaaring dumating ang mga datos sa maraming paraan at mga format. Ang isa sa mga pinaka karaniwang mga format ay CSV (mga halaga na pinaghiwalay ng kuwit). Ang data ng CSV ay napakainam. Ang mga file ay karaniwang may linya ng header na may pangalan ng mga patlang o haligi at hanay ng data kung saan ang bawat hanay ay naglalaman ng isang halaga sa bawat field, na pinaghihiwalay ng mga kuwit.

Narito ang isang maliit na snippet mula sa isang UFO sightings dataset (talaga). Ang unang hilera (header) ay naglalaman ng mga pangalan ng haligi, at ang iba pang mga linya ay naglalaman ng data. Makikita mo na madalas na walang laman ang column na "Mga Naulat na Mga Kulay":

1
City,Colors Reported,Shape Reported,State,Time
2
Ithaca,,TRIANGLE,NY,6/1/1930 22:00
3
Willingboro,,OTHER,NJ,6/30/1930 20:00
4
Holyoke,,OVAL,CO,2/15/1931 14:00
5
Abilene,,DISK,KS,6/1/1931 13:00
6
New York Worlds Fair,,LIGHT,NY,4/18/1933 19:00
7
Valley City,,DISK,ND,9/15/1934 15:30
8
Crater Lake,,CIRCLE,CA,6/15/1935 0:00
9
Alma,,DISK,MI,7/15/1936 0:00
10
Eklutna,,CIGAR,AK,10/15/1936 17:00
11
Hubbard,,CYLINDER,OR,6/15/1937 0:00
12
Fontana,,LIGHT,CA,8/15/1937 21:00
13
Waterloo,,FIREBALL,AL,6/1/1939 20:00
14
Belton,RED,SPHERE,SC,6/30/1939 20:00

Ang pagsusulat ng tipong ito ng data ng CSV sa isang file ay nagsasangkot ng ilang mga pagpapatakbo ng string pati na rin ang pagtatrabaho sa mga file. Bago tayo magtungo sa pangunahing kaisipan, narito ang mga sapilitang bahagi: ang kahulugan ng pakete, ang mga pag-import, at ang string ng data (tandaan ang paggamit ng const).

1
package main
2
3
import (
4
    "os"
5
  "strings"
6
	"bufio"
7
)
8
9
	data := `
10
    City,Colors Reported,Shape Reported,State,Time
11
    Ithaca,,TRIANGLE,NY,6/1/1930 22:00
12
    Willingboro,,OTHER,NJ,6/30/1930 20:00
13
    Holyoke,,OVAL,CO,2/15/1931 14:00
14
    Abilene,,DISK,KS,6/1/1931 13:00
15
    New York Worlds Fair,,LIGHT,NY,4/18/1933 19:00
16
    Valley City,,DISK,ND,9/15/1934 15:30
17
    Crater Lake,,CIRCLE,CA,6/15/1935 0:00
18
    Alma,,DISK,MI,7/15/1936 0:00
19
    Eklutna,,CIGAR,AK,10/15/1936 17:00
20
    Hubbard,,CYLINDER,OR,6/15/1937 0:00
21
    Fontana,,LIGHT,CA,8/15/1937 21:00
22
    Waterloo,,FIREBALL,AL,6/1/1939 20:00
23
    Belton,RED,SPHERE,SC,6/30/1939 20:00
24
	`

Ang main() function ay lumilikha ng isang file na tinatawag na "ufo-sightings.csv", sinusuri na walang pagkakamali, at pagkatapos ay lumilikha ng isang buffered manunulat w. Ang defer tawag sa susunod na linya, na flushes ang mga nilalaman ng buffer sa file, ay ginagamit sa dulo ng kagamitan. Iyon ay ang kahulugan ng paged-defer. Sa ganon, ginagamit nito ang Split() function ng mga string ng mga pakete upang palitan ang mga string ng mga datos sa mga indibidwal na mga linya.

Pagkatapos, sa loob ng for-loop, ang nangungunang at sumusunod na whitespace ay pinutol mula sa bawat linya. Ang mga walang laman na linya ay nilaktawan, at ang mga di-walang laman na mga linya ay isinulat sa buffer, na sinusundan ng isang newline na karakter. Ang buffer ay ibubuhos sa file sa dulo.

1
func main() {
2
    f, err := os.Create("ufo-sightings.csv")
3
	if err != nil {
4
		panic(e)
5
	}
6
7
	w := bufio.NewWriter(f)
8
	defer w.Flush()
9
	lines := strings.Split(data, "\n")
10
	for _, line := range lines {
11
		line := strings.Trim(line, " ")
12
		if line == "" {
13
			continue
14
		}
15
		w.WriteString(line)
16
		w.WriteString("\n")
17
	}
18
}

Ang pagbabasa mula sa file ay medyo simple:

1
package main 
2
3
import (
4
"fmt"
5
"io/ioutil"
6
)
7
8
9
func main() {
10
    data, err := ioutil.ReadFile("ufo-sightings.csv")
11
	if err != nil {
12
		panic(err)
13
	}
14
15
	fmt.Println(string(data))
16
}

Konklusyon

Ang Go ay may matibay na mga pasilidad upang harapin ang teksto ng lahat ng mga hugis at pag-encode. Sa bahaging ito ng serye, tiningnan namin ang mga pangunahing kaalaman ng representasyon ng teksto sa Pumunta, pagpoproseso ng teksto gamit ang mga string ng mga pakete, at pagharap sa mga file na CSV.

Sa bahagi ng dalawa, ilalagay namin ang natutunan namin sa pagsasanay upang linisin ang mga datos na hindi nakakalat sa paghahanda para sa pag-aaral.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.