1  So sánh data frame và tibble

library(dplyr)
library(knitr)

opts_chunk$set(
    message = FALSE
)

d <- data.frame(
    a = c(1, 0, 1, 0, 0),
    b = seq(5)
)

d
  a b
1 1 1
2 0 2
3 1 3
4 0 4
5 0 5

1.1 Tên hàng

Trong khi data frame có tên hàng, tibble không có.

rownames(d) <- c("a", "b", "c", "d", "e")
d
  a b
a 1 1
b 0 2
c 1 3
d 0 4
e 0 5
d_tib <- tibble(d)
d_tib
# A tibble: 5 × 2
      a     b
  <dbl> <int>
1     1     1
2     0     2
3     1     3
4     0     4
5     0     5

Muốn thêm tên hàng cho tibble, chúng ta tạo một cột mới.

d_tib <- tibble(tibble::rownames_to_column(d, "id"))
d_tib
# A tibble: 5 × 3
  id        a     b
  <chr> <dbl> <int>
1 a         1     1
2 b         0     2
3 c         1     3
4 d         0     4
5 e         0     5

Cũng vì lí do này, data frame có thể slice theo tên hàng, còn tibble thì không.

d[c("a", "b"), ]
  a b
a 1 1
b 0 2
d_tib %>% filter(id %in% c("a", "b"))
# A tibble: 2 × 3
  id        a     b
  <chr> <dbl> <int>
1 a         1     1
2 b         0     2

1.2 Slice cột

Để truy cập vào dữ liệu của một cột trong data frame, chúng ta có những cách sau.

d$a
[1] 1 0 1 0 0
d[, "a"]
[1] 1 0 1 0 0
d[, c("a")]
[1] 1 0 1 0 0

Những cách này trả về vector nếu chỉ slice một cột. Muốn giữ nguyên định dạng data frame (gọi là subset), chúng ta làm như sau.

d["a"]
  a
a 1
b 0
c 1
d 0
e 0

Thêm một cặp ngoặc vuông nữa, bạn cũng sẽ lấy được vector giá trị của cột.

d[["a"]]
[1] 1 0 1 0 0

Slicing bằng giá trị chuỗi kí tự của tên cột thuận lợi cho lập trình.

col_name <- "a"
d[[col_name]]
[1] 1 0 1 0 0

Đối với tibble, slicing luôn trả về subset.

d_tib["a"]
# A tibble: 5 × 1
      a
  <dbl>
1     1
2     0
3     1
4     0
5     0
d_tib[, "a"]
# A tibble: 5 × 1
      a
  <dbl>
1     1
2     0
3     1
4     0
5     0
d_tib[, c("a")]
# A tibble: 5 × 1
      a
  <dbl>
1     1
2     0
3     1
4     0
5     0

Để lấy vector, bạn có thể dùng các cách sau.

d_tib$a
[1] 1 0 1 0 0
d_tib[["a"]]
[1] 1 0 1 0 0
d_tib %>% pull(a)
[1] 1 0 1 0 0

Do vậy, muốn lập trình với tibble, bạn có thể làm như sau.

d_tib[[col_name]]
[1] 1 0 1 0 0

Hoặc

d_tib %>% pull(!!rlang::sym(col_name))
[1] 1 0 1 0 0

Tương tự, nếu muốn subset, bạn có thể làm như trên với hàm select().

d_tib %>% select(!!rlang::sym(col_name))
# A tibble: 5 × 1
      a
  <dbl>
1     1
2     0
3     1
4     0
5     0