Curățarea datelor cu drum Partea 1

Prezentare generală

Unul dintre cele mai importante aspecte ale oricărei aplicații este validarea intrării sale. Abordarea cea mai de bază este doar că nu reușește dacă intrarea nu satisface cerințele. Cu toate acestea, în multe cazuri acest lucru nu este suficient. În multe sisteme, colectarea datelor este separată de analiza datelor. Ar putea fi un sondaj sau un set de date vechi. 

În aceste cazuri, este necesar să treceți întregul set de date înainte de analiză, să detectați date nevalide sau lipsă, să remediați ceea ce poate fi stabilit și să semnalizați sau să eliminați datele care nu pot fi salvate. De asemenea, este util să furnizăm statistici privind calitatea datelor și tipurile de erori întâlnite. 

În această serie din două părți veți învăța cum să utilizați facilitățile de text ale Go, fișierele CSV de felie și zaruri și asigurați-vă că datele dvs. sunt curate. În prima parte, ne vom concentra pe temelia prelucrării textului în Go-bytes, runes și string-uri, precum și lucrul cu fișierele CSV.

Text în Go

Înainte de a ne scufunda în curățarea datelor, să începem cu fundația textului în Go. Blocurile sunt blocuri, rulete și șiruri de caractere. Să vedem ce reprezintă fiecare dintre noi și care sunt relațiile dintre ele. 

bytes

Bytes-urile sunt numere pe 8 biți. Fiecare octet poate reprezenta una dintre cele 256 valori posibile (2 la puterea de 8). Fiecare caracter din setul de caractere ASCII poate fi reprezentat de un singur octet. Dar sunt octeți nu de caractere. Motivul este că Go ca limbă modernă acceptă Unicode, unde există mai mult de 256 de caractere separate. Introduceți rune. 

Runes

O rună în Go este un alt nume pentru tipul int32. Aceasta înseamnă că fiecare rună poate reprezenta mai mult de patru miliarde de valori separate (2 la puterea de 32), care este suficient de bună pentru a acoperi întregul set de caractere Unicode. 

În următorul cod puteți vedea că runa "Δ" (alt-J pe Mac) este doar un int32. Pentru a imprima caracterul pe ecran, trebuie să îl convertesc la un șir.

pachetul principal de import ("fmt") func principal () r: = 'Δ' fmt.Println (r) fmt.Println (int32 (r)) fmt.Println 

Unicode este complicat. O rună reprezintă oficial un punct de cod Unicode. Caracterele Unicode sunt reprezentate de obicei printr-un singur punct de cod Unicode, dar uneori mai mult de unul.

Siruri de caractere

Șirurile sunt în mod oficial doar niște felii de octeți. Dacă indexați un șir, primiți un octet înapoi:

func principal () s: = "abc" pentru i: = 0; eu < len(s); i++  fmt.Println(s[i])   Output: 97 98 99 

Straturile de literă sunt o secvență de caractere UTF-8 închise în ghilimele duble. Acestea pot conține secvențe de evacuare, care reprezintă un backslash urmat de un caracter ASCII, cum ar fi \ n (linie nouă) sau \ t (Tab). Au înțelesuri speciale. Iată lista completă:

\ a U + 0007 alertă sau clopot \ b U + 0008 backspace \ f U + 000C formă de alimentare \ n U + 000A linie de alimentare sau linie nouă U + 000D carriage return \ t U + 0009 orizontală tab \ v U + 000b verticală fila \\ U + 005c backslash \ 'U + 0027 cotație unică (valabilă numai în literatura rune) \ "U + 0022 dublă cotație (validă numai în literalurile de șir) 

Uneori este posibil să doriți să stocați octeți literali direct într-un șir, indiferent de secvențele de evacuare. Ai putea scăpa de fiecare spate, dar asta e plictisitor. O abordare mult mai bună este de a folosi șiruri brute care sunt închise în spate. 

Iată un exemplu de șir cu a \ t (tab) secvență de evacuare, care este reprezentată odată ca atare, apoi cu ieșirea din spate, apoi ca un șir brut:

funcția principală () s1: = "1 \ t2" s2: = "1 \\ t2" s3: = 1 \ t2 'fmt.Printin (s1) fmt.Println (s2) : 1 2 1 \ t2 1 \ t2 

În timp ce șiruri de caractere sunt felii de octeți, atunci când iterați peste un șir cu o instrucțiune pentru interval, obțineți o rună în fiecare iterație. Aceasta înseamnă că puteți obține unul sau mai mulți octeți. Acest lucru este ușor de văzut cu indexul pentru interval. Iată un exemplu nebun. Cuvântul ebraic "שלום" înseamnă "Bună" (și pace). Evrei este de asemenea scrisă din dreapta în stânga. Voi construi un șir care amestecă cuvântul ebraic cu traducerea în limba engleză. 

Apoi, voi imprima rula cu rune, inclusiv indicele de octet al fiecărei runde din sir. După cum veți vedea, fiecare rună evrei are două octeți, în timp ce personajele engleze iau un octet, deci lungimea totală a acestui șir este de 16 octeți, deși are patru caractere ebraice, trei simboluri și cinci caractere englezești (12 caractere ). De asemenea, personajele evreiești vor fi afișate de la dreapta la stânga:

functie () hello: = "שלום = hello" fmt.Println ("lungime:", len (hello)  Ieșire: lungime: 16 0 ש 2 ל 4 ו 6 ם 8 9 = 10 11 h 12 e 13 l 14 l 15 o 

Toate aceste nuanțe pot fi extrem de importante atunci când aveți un set de date pentru a curăța cu citate ciudate și un amestec de caractere și simboluri Unicode.

Când imprimați șiruri de caractere și secțiuni de octeți, există mai mulți specificatori de format care funcționează la fel în ambele. % s format imprimă octeți ca atare, %X imprimă două caractere hexazecimale în litere mici pe octet, %X imprimă două caractere hexazecimale majuscule pe octet și % q imprimă un șir dublu cotat evadat cu sintaxă go. 

Pentru a scăpa de semnul% din interiorul unui specificator de șir de formate, dublați-l. Pentru a separa octeții în timpul utilizării %X sau %X, puteți adăuga un spațiu, ca în "% x" și "% X". Aici este demo-ul:

funcția principală () s: = "שלום" fmt.Printf ("%% s format:% s \ n", s) fmt.Printf ("%% x format:% x \ n", s) ("%% format X:% X \ n", s) fmt.Printf ("%% x format:% x \ n" ) fmt.Printf ("%% q format:% q \ n", s) Ieșire: format% s: Format: format x7: Formatul X: D7 A9 D7 9C D7 95 D7 9D Format% q: "שלום"

Citirea și scrierea fișierelor CSV

Datele pot ajunge în mai multe moduri și formate. Unul dintre cele mai comune formate este CSV (valori separate prin virgulă). Datele CSV sunt foarte eficiente. Fișierele au, de obicei, o linie de antet cu numele câmpurilor sau coloanelor și rândurilor de date în care fiecare rând conține o valoare pe câmp, separate prin virgule. 

Iată un fragment mic dintr-un set de date privind OZN-urile (într-adevăr). Primul rând (antetul) conține numele coloanelor, iar celelalte linii conțin datele. Puteți observa că coloana "Colore raportate" este deseori goală:

Orașul, culorile raportate, forma raportată, statul, Timpul Ithaca ,, TRIANGLE, NY, 6/1/1930 22:00 Willingboro ,, ALTE, NJ, 6/30/1930 20:00 Holyoke ,, OVAL, CO, 2 / 15/1931 14:00 Abilene ,, DISK, KS, 6/1/1931 13:00 Târgul Lumii din New York ,, 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 / 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, SPHERE, SC, 6/30/1939 20:00 

Scriind această bucată de date CSV într-un fișier implică unele operații de șir, precum și lucrul cu fișiere. Înainte de a ne arunca în logica principală, aici sunt părțile obligatorii: definiția pachetului, importurile și șirul de date (notați utilizarea const).

pachet import principal ("os" "stringuri" "bufio") date: = 'Orașul, , 6/30/1930 20:00 Holyoke ,, OVAL, CO, 2/15/1931 14:00 Abilene ,, DISK, KS, 6/1/1931 13:00 Târgul Lumii din New York ,, LIGHT, NY, 4 / 18/1933 19:00 Valea Cetății ,, DISK, ND, 9/15/1934 15:30 Crater Lake ,, CIRCLE, CA, 6/15/1935 0:00 Alma ,, DISK, MI, 7 / 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 ,, FIREBALL, AL, 6/1/1939 20:00 Belton, RED, SPHERE, SC, 6/30/1939 20:00 ' 

principal() funcția creează un fișier numit "ufo-sightings.csv", verifică dacă nu există nici o eroare și apoi creează un scriitor tamponat w. amâna apelați în linia următoare, care dezactivează conținutul tamponului în fișier, se execută la sfârșitul funcției. Acesta este sensul de amânare. Apoi, utilizează Despică() funcția pachetului de șiruri de caractere pentru a sparge șirurile de date în linii individuale. 

Apoi, în interiorul for-buclă, spațiile de culori ale vederii și ale traseului sunt tăiate din fiecare linie. Liniile goale sunt sărite și liniile non-goale sunt înscrise în memoria tampon, urmată de un caracter nou. Asta e. Tamponul va fi înfundat în fișier în cele din urmă.

Funcționarea funcției () f, err: = os.Create ("ufo-sightings.csv") dacă err! = nil panic (e) w: = bufio.NewWriter = stringuri.Split (date, "\ n") pentru _, line: = liniile de linie line: = strings.Trim (line, "") dacă linia == "" continue w.WriteString (line) w. WriteString ("\ n")

Citirea din fișier este destul de simplă:

pachet import principal ("fmt" "io / ioutil") func main () date, err: = ioutil.ReadFile ("ufo-sightings.csv" șir (date))

Concluzie

Go are facilități puternice pentru a face față textului de toate formele și codificările. În această parte a seriei, am analizat elementele de bază ale reprezentării textului în Go, procesarea textului utilizând pachetul de șiruri și tratarea fișierelor CSV. 

În partea a doua, vom pune ceea ce am învățat în practică pentru a curăța date dezordonate în pregătirea pentru analiză.

Cod