tibble

tibble は、データフレームを現代風にアレンジしたものである。 時代の試練に耐えるフィーチャを残し、昔は便利だったが今は不満に思うフィーチャを捨てる(例: 文字ベクタを係数に変換する)。

library(tibble)

作成中

tibble() は、データフレームを作成するのに適した方法である。 データフレームのベストプラクティスをカプセル化したものである。

強制

tibble() を補完するために、tibble はオブジェクトを tibble に強制するための as_tibble() を提供する。 一般に、as_tibble() の方法は、as.data.frame() の方法よりはるかに単純である。 リスト用のメソッドは、パフォーマンスを重視して書かれている。

l <- replicate(26, sample(100), simplify = FALSE)
names(l) <- letters

timing <- bench::mark(
  as_tibble(l),
  as.data.frame(l),
  check = FALSE
)

timing
#> # A tibble: 2 × 14
#>   expression       min         mean         median      max         `itr/sec`
#>   <chr>            <bench_tm>  <bench_tm>   <bench_tm>  <bench_tm>      <dbl>
#> 1 as_tibble(l)     0.000287696 0.0006251376 0.000327178 0.004508219     1600.
#> 2 as.data.frame(l) 0.000791522 0.0016640039 0.001098172 0.007652914      601.
#> # … with 8 more variables: mem_alloc <bnch_byt>, n_gc <dbl>, n_itr <int>,
#> #   total_time <bench_tm>, result <list>, memory <list>, time <list>, gc <list>

as.data.frame() の速度は、対話的に使用する場合には通常ボトルネックにはならないが、何千もの乱雑な入力を一つの整然としたデータフレームにまとめる場合には問題になることがある。

tibble vs data frames {#tibble -vs-data-frames}

tibble とデータフレームの主な違いは、表示、部分集合、リサイクルルールの3点である。

印刷

tibble を表示すると、1画面に収まる最初の10行とすべての列だけが表示される。 また、列の種類を省略した説明を表示し、フォントスタイルと色を使用して強調表示す。

tibble(x = -5:100, y = 123.456 * (3 ^ x))
#> # A tibble: 106 × 2
#>        x         y
#>    <int>     <dbl>
#>  1    -5     0.508
#>  2    -4     1.52 
#>  3    -3     4.57 
#>  4    -2    13.7  
#>  5    -1    41.2  
#>  6     0   123.   
#>  7     1   370.   
#>  8     2  1111.   
#>  9     3  3333.   
#> 10     4 10000.   
#> # … with 96 more rows

数値はデフォルトで有効数字3桁で表示され、末尾には分数成分の存在を示すドットが表示される。

オプションでデフォルトの外観を制御することができる。

利用可能なオプションについては ?pillar::pillar_options?tibble_options を、型の省略形の概要については vignette("types") を、数値の書式の詳細については vignette("numbers") を、データフレーム表示との比較については vignette("digits") を参照。

部分集合

tibble は部分集合に対してかなり厳格である。 [ は常に別の tibble を返す。 データフレームとは対照的である。[ はデータフレームを返すこともあれば、単にベクタを返すこともある。

df1 <- data.frame(x = 1:3, y = 3:1)
class(df1[, 1:2])
#> [1] "data.frame"
class(df1[, 1])
#> [1] "integer"

df2 <- tibble(x = 1:3, y = 3:1)
class(df2[, 1:2])
#> [1] "tbl_df"     "tbl"        "data.frame"
class(df2[, 1])
#> [1] "tbl_df"     "tbl"        "data.frame"

1つの列を抽出するには、[[ または $ を使用する。

class(df2[[1]])
#> [1] "integer"
class(df2$x)
#> [1] "integer"

tibble はまた、$ に厳しい。 tibble は部分マッチを決して行わず、列が存在しない場合は警告を投げ、NULL を返す。

df <- data.frame(abc = 1)
df$a
#> [1] 1

df2 <- tibble(abc = 1)
df2$a
#> Warning: Unknown or uninitialised column: `a`.
#> NULL

ただし、tibble は、drop 引数が提供された場合、それを尊重する。

data.frame(a = 1:3)[, "a", drop = TRUE]
#> [1] 1 2 3
tibble(a = 1:3)[, "a", drop = TRUE]
#> [1] 1 2 3

tibble は行名をサポートしていない。 これらは、 tibble への変換時や部分集合時に除去される。

df <- data.frame(a = 1:3, row.names = letters[1:3])
rownames(df)
#> [1] "a" "b" "c"
rownames(as_tibble(df))
#> [1] "1" "2" "3"

tbl <- tibble(a = 1:3)
rownames(tbl) <- letters[1:3]
#> Warning: Setting row names on a tibble is deprecated.
rownames(tbl)
#> [1] "a" "b" "c"
rownames(tbl[1, ])
#> [1] "1"

tibble とデータフレームの詳細な比較は、vignette("invariants") を参照。

リサイクル

tibble を構成する場合、長さ1の値のみが再利用される。 長さが1でない最初の列は、 tibble の行数を決定するため、競合によりエラーが発生する。

tibble(a = 1, b = 1:3)
#> # A tibble: 3 × 2
#>       a     b
#>   <dbl> <int>
#> 1     1     1
#> 2     1     2
#> 3     1     3
tibble(a = 1:3, b = 1)
#> # A tibble: 3 × 2
#>       a     b
#>   <int> <dbl>
#> 1     1     1
#> 2     2     1
#> 3     3     1
tibble(a = 1:3, c = 1:2)
#> Error:
#> ! Tibble columns must have compatible sizes.
#> • Size 3: Existing data.
#> • Size 2: Column `c`.
#> ℹ Only values of size one are recycled.

また、これはゼロ行の tibble にも適用され、プログラミングにおいて重要な場合がある。

tibble(a = 1, b = integer())
#> # A tibble: 0 × 2
#> # … with 2 variables: a <dbl>, b <int>
tibble(a = integer(), b = 1)
#> # A tibble: 0 × 2
#> # … with 2 variables: a <int>, b <dbl>

算術演算

データフレームと異なり、 tibble は全列の算術演算をサポートしない。 結果は黙ってデータフレームに強制される。 この動作は、今後のバージョンアップでエラーになる可能性があるので、当てにしないでみよう。

tbl <- tibble(a = 1:3, b = 4:6)
tbl * 2
#>   a  b
#> 1 2  8
#> 2 4 10
#> 3 6 12