使用Go清理数据:第1部分

总览

任何应用程序最重要的方面之一就是验证其输入。 如果输入不满足要求,最基本的方法就是失败。 但是,在许多情况下,这还不够。 在许多系统中,数据收集与数据分析是分开的。 它可能是调查或旧数据集。

在这些情况下,有必要在分析之前遍历整个数据集,检测无效或丢失的数据,修复可修复的内容,并标记或删除无法挽救的数据。 提供有关数据质量和遇到哪种错误的统计信息也很有用。

在这个由两部分组成的系列文章中,您将学习如何使用Go的文本工具,对CSV文件进行切片和切块,并确保数据一尘不染。 在第一部分中,我们将重点介绍Go语言中文本,字节,符文和字符串等文本处理的基础,以及使用CSV文件的基础。

Go中的文字

在深入研究数据清理之前,让我们从Go的文本基础开始。 构建块是字节,符文和字符串。 让我们看看每个人代表什么以及他们之间的关系。

字节数

字节是8位数字。 每个字节可以表示可能的256个值之一(2的8的幂)。 ASCII字符集中的每个字符都可以由一个字节表示。 但是字节不是字符。 原因是Go作为一种现代语言支持Unicode,其中有超过256个单独的字符。 输入符文。

符文

Go中的符文是int32类型的别称。 这意味着每个符文可以表示超过40亿个单独的值(2等于32的幂),足以覆盖整个Unicode字符集。

在以下代码中,您可以看到符文“ ∆”(在Mac上为alt-J)只是一个int32。 为了将它代表的字符打印到屏幕上,我必须将其转换为字符串。

package main

import (
    "fmt"
)


func main() {
    r := '∆'
    fmt.Println(r)
    fmt.Println(int32(r))
    fmt.Println(string(r))
}

Output:

8710
8710
∆

Unicode很复杂。 符文正式代表Unicode代码点。 Unicode字符通常由单个Unicode代码点表示,但有时不止一个。

弦乐

字符串正式是只读的字节片。 如果索引一个字符串,则返回一个字节:

func main() {
    s := "abc"
    for i := 0; i < len(s); i++ {
        fmt.Println(s[i])        
    }
}

Output:

97
98
99

字符串文字是用双引号括起来的一系列UTF-8字符。 它们可能包含转义序列,它们是反斜杠,后跟ASCII字符,例如\n (换行符)或\t (制表符)。 它们具有特殊的含义。 这是完整列表:

\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)

有时,您可能希望直接将文字字节存储在字符串中,而与转义序列无关。 您可以避开每个反斜杠,但这很乏味。 更好的方法是使用反引号中包含的原始字符串。

这是一个带有\t (制表符)转义序列的字符串的示例,该字符串按原样表示一次,然后使用反斜杠转义,然后作为原始字符串表示:

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

尽管字符串是字节的切片,但是当您使用for-range语句遍历字符串时,每次迭代都会得到一个符文。 这意味着您可能会获得一个或多个字节。 使用for-range索引很容易看到这一点。 这是一个疯狂的例子。 希伯来语单词“שלום”的意思是“你好”(和和平)。 希伯来语也从右到左书写。 我将构造一个将希伯来语单词及其英语翻译混合在一起的字符串。

然后,我将按符文打印该符文,包括字符串中每个符文的字节索引。 如您所见,每个希伯来文符文占用两个字节,而英文字符则占用一个字节,因此即使该字符串有四个希伯来语字符,三个符号和五个英文字符(12个字符),该字符串的总长度为16个字节。 )。 此外,希伯来语字符将从右向左显示:

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

当您有一个数据集要用怪异的引号和Unicode字符和符号混合进行清理时,所有这些细微差别都非常重要。

当打印字符串和字节片时,有几种格式说明符在两者上都相同。 %s格式按原样打印字节, %x每个字节打印两个小写十六进制字符, %X每个字节打印两个大写十六进制字符, %q打印使用go语法转义的双引号字符串。

要在格式字符串说明符中转义%符号,只需将其加倍即可。 要在使用%x%X时分隔字节,可以添加空格,如“%x”和“%X”。 这是演示:

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:  "שלום"

读写CSV文件

数据可以多种方式到达。 CSV(逗号分隔值)是最常见的格式之一。 CSV数据非常有效。 文件通常在标题行中包含字段或数据列和数据行的名称,其中每一行包含每个字段的值,并用逗号分隔。

这是UFO目击数据集的一个小片段(确实)。 第一行(标题)包含列名,其他行包含数据。 您会发现“报告的颜色”列通常为空:

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

将这部分CSV数据写入文件需要进行一些字符串操作以及使用文件。 在深入探讨主要逻辑之前,这里有一些必不可少的部分:包定义,导入和数据字符串(请注意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
	`

main()函数创建一个名为“ ufo-sightings.csv”的文件,检查是否没有错误,然后创建一个缓冲的编写器w 。 下一行的defer调用将缓冲区的内容刷新到文件中,该调用在函数末尾执行。 那就是延期的意思。 然后,它使用字符串包的Split()函数将数据字符串分成几行。

然后,在for循环内部,从每行修剪前导和尾随空白。 空行将被跳过,非空行将被写入缓冲区,后跟换行符。 而已。 最后,缓冲区将刷新到文件中。

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")
	}
}

从文件读取非常简单:

package main 

import (
"fmt"
"io/ioutil"
)


func main() {
    data, err := ioutil.ReadFile("ufo-sightings.csv")
	if err != nil {
		panic(err)
	}

	fmt.Println(string(data))
}

结论

Go具有强大的功能来处理各种形状和编码的文本。 在本系列的这一部分中,我们研究了Go语言中的文本表示,使用字符串包进行文本处理以及处理CSV文件的基础知识。

在第二部分中,我们将把学到的知识付诸实践,以清理凌乱的数据,为分析做准备。

翻译自: https://code.tutsplus.com/tutorials/cleaning-up-your-data-with-go-part-1--cms-30298

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值