美文网首页R
R 数据处理(七)

R 数据处理(七)

作者: 名本无名 | 来源:发表于2021-01-18 12:52 被阅读0次

    前言

    在前面的介绍中,我们使用到了 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 的页脚打印多少额外的列名?

    相关文章

      网友评论

        本文标题:R 数据处理(七)

        本文链接:https://www.haomeiwen.com/subject/svyaaktx.html