R

R 数据处理(五)

2021-01-16  本文已影响0人  名本无名

前言

前面我们讲到了 readr 的解析器,总共有 8 个解析函数。

下面我们具体介绍每个解析函数的用法

解析器

1. 数值

对数值的解析看起来挺简单的,但其实有几个问题需要解决:

  1. 世界上不同地区的人写数字的方式会有所不同,比如,一些国家使用 . 来区分实数的整数部分和小数部分,而其他国家使用 , 来区分

  2. 数字在不同的使用场景会被不同的字符包裹,比如 $100010%

  3. 数字通常包含分组字符,方便阅读。例如 1,000,000

为了解决第一个问题,readr 提供了 locale 参数来指定不同地区的解析方式。

解析数字时,最重要的选项是用于小数点的字符,你可以设置新的 locale 并指定 decimal_mark 参数的值来覆盖默认的 .

> parse_double("1.23")
[1] 1.23
> parse_double("1,23", locale = locale(decimal_mark = ","))
[1] 1.23

parse_number() 用于解决第二个问题:它会忽略数字前后的非数字字符,这对货币和百分比数字特别有用,但也适用于提取文本中嵌入的数字

> parse_number("$100")
[1] 100
> parse_number("20%")
[1] 20
> parse_number("It cost $123.45")
[1] 123.45

最后一个问题可以通过结合 parse_number()locale 来忽略分组标记

# Used in America
> parse_number("$123,456,789")
[1] 123456789

# Used in many parts of Europe
> parse_number("123.456.789", locale = locale(grouping_mark = "."))
[1] 123456789

# Used in Switzerland
> parse_number("123'456'789", locale = locale(grouping_mark = "'"))
[1] 123456789

2. 字符串

parse_character() 来解析字符串看起来应该是很简单的,能够直接把输入返回。

但是,生活并不是那么简单的,因为同一个字符串的表示方法有很多种。

为了理解解析时发生了,我们需要深入了解计算机如何来表示字符串的。在 R 中,我们可以使用 charToRaw() 获得字符串的底层表示形式

> charToRaw("Hadley")
[1] 48 61 64 6c 65 79

每个十六进制数代表一个字节的信息,48 表示 H, 61 表示 a 等等。从十六进制数到字符的映射称为编码,在这种情况下编码称为 ASCII

ASCII 在表示英语字符方面做得很好,因为它是美国信息交换的标准代码

而对于非英文来说,事情就变得更加复杂了点。在计算机早期时代,有许多编码非英语字符的竞争标准,要正确解释一个字符串,您需要同时知道值和编码

例如,两种常见的编码 Latin1(ISO-8859-1,用于西欧语言)和 Latin2(ISO-8859-2,用于东欧语言)。在 Latin1 中,字节 b1 表示 ±,但是在 Latin2 中表示的是 ą

幸运的是,现在有一个标准几乎在所有地方都能够得到支持:UTF-8UTF-8 可以编码当今人类使用的几乎所有字符,以及许多额外的符号(比如 emoji

readr 使用的都是 UTF-8,它假设您的数据在读取时是 UTF-8 编码的,并且在写入时也总是使用它。

如果你的系统不支持 UTF-8 格式(你的机子不会老到这种程度的),那它看起来可能非常奇怪,已经发生了乱码。

看个例子

> x1 <- "El Ni\xf1o was particularly bad this year"
> x2 <- "\x82\xb1\x82\xf1\x82\xc9\x82\xbf\x82\xcd"

> x1
[1] "El Ni\xf1o was particularly bad this year"
> x2
[1] "\x82\xb1\x82\xf1\x82\u0242\xbf\x82\xcd"

非英文字符并未被正确转译

使用 parse_character() 时指定编码格式

parse_character(x1, locale = locale(encoding = "Latin1"))
#> [1] "El Niño was particularly bad this year"
parse_character(x2, locale = locale(encoding = "Shift-JIS"))
#> [1] "こんにちは"

那如果我们不知道字符串的编码方式,要如何解码出正确的字符呢?

如果幸运的话,它会在数据文档中的某个地方。不幸的是,这种情况很少发生,因此 readr 提供了 guess_encoding() 来帮助您解决这个问题

它也并不是万无一失的,当你有大量的文本时效果会更好,但它是一个合理的起点。在找到合适的编码之前,可以尝试几种不同的编码。

> guess_encoding(charToRaw(x1))
# A tibble: 2 x 2
  encoding   confidence
  <chr>           <dbl>
1 ISO-8859-1       0.46
2 ISO-8859-9       0.23

> guess_encoding(charToRaw(x2))
# A tibble: 1 x 2
  encoding confidence
  <chr>         <dbl>
1 KOI8-R         0.42

guess_encoding() 的第一个参数可以是文件的路径,也可以是字符串的原始向量

3. 因子

R 使用因子来表示一组所有可能值已知的分类变量。

通过向 parse_factor()levels 参数传入一个已知的向量作为分类向量,当出现意外的值时会生成警告信息

> fruit <- c("apple", "banana")
> parse_factor(c("apple", "banana", "bananana"), levels = fruit)
Warning: 1 parsing failure.
row col           expected   actual
  3  -- value in level set bananana

[1] apple  banana <NA>  
attr(,"problems")
# A tibble: 1 x 4
    row   col expected           actual  
  <int> <int> <chr>              <chr>   
1     3    NA value in level set bananana
Levels: apple banana

4. 时间和日期

你可以根据需要从三个解析器中选择相应的解析器

[1] "2010-10-01 20:10:00 UTC"
> parse_datetime("20101010")
[1] "2010-10-10 UTC"
> parse_date("2010-10-01")
[1] "2010-10-01"
> parse_time("01:10 am")
01:10:00
> parse_time("20:10:01")
20:10:01

如果这些默认值不适用于您的数据,您可以提供自己的日期时间格式,由以下几部分组成

Year

Month

Day

Time

Non-digits

示例

> parse_date("01/02/15", "%m/%d/%y")
[1] "2015-01-02"
> parse_date("01/02/15", "%d/%m/%y")
[1] "2015-02-01"
> parse_date("01/02/15", "%y/%m/%d")
[1] "2001-02-15"

如果 %B%b 使用的是非英语的月份名,你需要用 locale() 设置语言。

详情参见 date_names_langs() 中的内置语言列表,或者如果没有包含你的语言,可以用 date_names() 创建你自己的语言

> parse_date("1 janvier 2015", "%d %B %Y", locale = locale("fr"))
[1] "2015-01-01"

最后,是上节的思考练习。是一位读者写的,我发出来给大家参考参考

( ̄▽ ̄)~*

http://note.youdao.com/s/Ls1QE1oN

上一篇 下一篇

猜你喜欢

热点阅读