R 数据处理 —— tibble

前言

在前面的介绍中,我们使用到了 tibbles 这种数据结构。

这是 tidyverse 包定义的类似于 R 传统的 data.frame

R 语言产生到现在也挺久了,一些 10 年或 20 年前很有用的东西现在不一定同样有用。在不破坏现有代码的情况下想要改变 R 的基础数据结构是很困难的,所以大多数的创新都是在开发新包中。

在这里,我们将介绍 tibble

首先,导入 tidyverse

library(tidyverse)
# or 
library(tibble)

构造 tibbles

tibblestidyverse 包的特性之一,几乎所有函数都会生成 tibbles

绝大多数的 R 包都是使用常规的 data.frame,如果你想将其转换为 tibble,你可以使用 as_tibble()

> as_tibble(iris)
# A tibble: 150 x 5
   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
          <dbl>       <dbl>        <dbl>       <dbl> <fct>  
 1          5.1         3.5          1.4         0.2 setosa 
 2          4.9         3            1.4         0.2 setosa 
 3          4.7         3.2          1.3         0.2 setosa 
 4          4.6         3.1          1.5         0.2 setosa 
 5          5           3.6          1.4         0.2 setosa 
 6          5.4         3.9          1.7         0.4 setosa 
 7          4.6         3.4          1.4         0.3 setosa 
 8          5           3.4          1.5         0.2 setosa 
 9          4.4         2.9          1.4         0.2 setosa 
10          4.9         3.1          1.5         0.1 setosa 
# … with 140 more rows

你可以用 tibble() 从单个向量创建一个新的 tibbletibble() 会自动循环长度为 1 的输入,并允许您引用刚刚创建的变量,如下所示。

> tibble(
+     x = 1:5, 
+     y = 1, 
+     z = x ^ 2 + y
+ )
# A tibble: 5 x 3
      x     y     z
  <int> <dbl> <dbl>
1     1     1     2
2     2     1     5
3     3     1    10
4     4     1    17
5     5     1    26

如果你对 data.frame() 很熟悉,可以看出 tibble 做的很少:它不会更改输入的类型(例如,不会将字符串转换为因子),同时也不会更改变量的名称,也不会创建行名。

tibble 允许无效的 R 变量名称作为列名,也就是非语法名称。

例如,它们可能不以字母开头,或者可能包含特殊的字符,如空格等。为了引用这些变量,需要用 ` 将它们引起来。

> tb <- tibble(
+     `:)` = "smile", 
+     ` ` = "space",
+     `2000` = "number"
+ )
> tb
# A tibble: 1 x 3
  `:)`  ` `   `2000`
  <chr> <chr> <chr> 
1 smile space number

在其他包(如 ggplot2dplyrtidyr)中使用这些变量时,也需要用 ` 包裹。

创建 tibble 的另一个方法是 tribble(),是 transposed tibble 的缩写。

tribble() 是为了在代码中输入数据而定制的,列名由公式定义(即,它们以 ~ 开头),条目之间用逗号分隔,如

> tribble(
+     ~x, ~y, ~z,
+     #--|--|----
+     "a", 2, 3.6,
+     "b", 1, 8.5
+ )
# A tibble: 2 x 3
  x         y     z
  <chr> <dbl> <dbl>
1 a         2   3.6
2 b         1   8.5

通常可以添加一行 # 开头的注释,来标明表头的位置

tibbles vs. data.frame

tibblesdata.frame 之间主要有两个区别:

  • 打印
  • 子集
1. 打印

tibbles 有一个精巧的打印方法,只显示前 10 行和适应屏幕上的所有列,这使得处理大数据更加容易。

除了名称之外,每列都会显示其类型,这是从 str() 中借鉴来的一个很好的特性

> (df <- tibble(
+     a = lubridate::now() + runif(1e3) * 86400,
+     b = lubridate::today() + runif(1e3) * 30,
+     c = 1:1e3,
+     d = runif(1e3),
+     e = sample(letters, 1e3, replace = TRUE)
+ ))
# A tibble: 1,000 x 5
   a                   b              c     d e    
   <dttm>              <date>     <int> <dbl> <chr>
 1 2021-01-17 14:24:00 2021-02-01     1 0.928 a    
 2 2021-01-17 06:19:44 2021-02-14     2 0.162 y    
 3 2021-01-16 17:42:21 2021-01-16     3 0.133 k    
 4 2021-01-17 09:27:45 2021-01-30     4 0.669 c    
 5 2021-01-17 10:49:48 2021-02-03     5 0.596 b    
 6 2021-01-16 19:11:51 2021-02-14     6 0.283 i    
 7 2021-01-17 06:49:47 2021-02-02     7 0.348 m    
 8 2021-01-16 17:12:39 2021-02-07     8 0.321 g    
 9 2021-01-16 18:12:05 2021-01-23     9 0.726 c    
10 2021-01-17 03:24:03 2021-02-11    10 0.950 d    
# … with 990 more rows

tibbles 的设计使您在打印大数据帧时不会意外地淹没控制台,R 的这个毛病真是实力劝退。

但有时需要比默认显示更多的输出。有几个选项可以帮助你

首先,可以显式地 print() 数据框并控制行数和列的宽度。width = Inf 将会显示所有列

> df %>% print(n=5, width=Inf)
# A tibble: 1,000 x 5
  a                   b              c     d e    
  <dttm>              <date>     <int> <dbl> <chr>
1 2021-01-16 23:20:47 2021-02-07     1 0.460 i    
2 2021-01-17 10:18:31 2021-02-08     2 0.384 w    
3 2021-01-17 00:06:15 2021-02-11     3 0.188 s    
4 2021-01-17 04:53:02 2021-02-10     4 0.328 j    
5 2021-01-16 23:13:51 2021-01-31     5 0.445 m    
# … with 995 more rows

您还可以通过设置以下选项来控制默认打印行为

# 如果多于 n 行,只打印 m 行。
options(tibble.print_max = n, tibble.print_min = m)

# 总是显示所有行
options(tibble.print_min = Inf)

# 无论屏幕的宽度如何,始终打印所有列
options(tibble.width = Inf)
2. 子集

到目前为止,你所学的所有工具都可以处理完整的数据框。

如果你想提取一个变量,你需要一些新的工具:$[[[[ 可以按名称或者位置提取,$ 只能按名称提取,但输入的符号更少。

> df <- tibble(
+     x = runif(5),
+     y = rnorm(5)
+ )
# Extract by name
> df$x
[1] 0.18390961 0.49066767 0.08295448 0.07084228 0.25732377
> df[["x"]]
[1] 0.18390961 0.49066767 0.08295448 0.07084228 0.25732377
# Extract by position
> df[[1]]
[1] 0.18390961 0.49066767 0.08295448 0.07084228 0.25732377

如果想要使用管道操作,需要使用特殊的占位符 .

> df %>% .$x
[1] 0.18390961 0.49066767 0.08295448 0.07084228 0.25732377
> df %>% .[["x"]]
[1] 0.18390961 0.49066767 0.08295448 0.07084228 0.25732377

相较于 data.frametibble 更严格。它们从不进行部分匹配,如果你访问的列不存在,它们将生成警告

4. 与旧代码交互

一些比较旧的代码不再适用于 tibble,如果遇到这种函数,那就用 as.data.frame() 转换为 data.frame 格式

> as.data.frame(df)
           x           y
1 0.18390961 -0.08348267
2 0.49066767 -0.15224540
3 0.08295448  0.89195578
4 0.07084228  0.62134132
5 0.25732377 -1.13856797
> class(as.data.frame(df))
[1] "data.frame"

一些旧函数不能与 tibble 一起工作的主要原因是 [ 函数,因为 dplyr::filter()dplyr::select() 函数允许你使用更加清晰的代码解决相同的问题,所以并不是很需要 [ 函数

对于 R 数据框,[ 有时候返回数据框,有时候返回一个向量,而对于 tibble[ 返回的总是另一个 tibble

5. 练习题
  1. 怎么分辨一个对象是否是 tibble

  2. 对比 data.frame 和等效的 tibble 操作,有什么区别?为什么默认的数据框行为会让你感到沮丧?

df <- data.frame(abc = 1, xyz = "a")
df$x
df[, "xyz"]
df[, c("abc", "xyz")]
  1. 如果您有一个存储在对象中的变量名,例如 var <- "mpg",如何从 tibble 中提取对应的变量呢?

  2. 练习从下面的数据框中引用非语法名称

  • 提取名为 1 的变量
  • 绘制 12 的散点图
  • 创建一个名为 3 的新列,它是 2 的值除以 1 的值
  • 将列重命名为 onetwothree
annoying <- tibble(
  `1` = 1:10,
  `2` = `1` * 2 + rnorm(length(`1`))
)
  • tibble::enframe() 函数的作用是什么?什么时候使用它?
  • 哪个选项控制在 tibble 的页脚打印多少额外的列名?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

名本无名

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值