tibble は、データフレームを現代風にアレンジしたものである。 時代の試練に耐えるフィーチャを残し、昔は便利だったが今は不満に思うフィーチャを捨てる(例: 文字ベクタを係数に変換する)。
library(tibble)
tibble()
は、データフレームを作成するのに適した方法である。 データフレームのベストプラクティスをカプセル化したものである。
入力の型を変更することはない (すなわち、もう stringsAsFactors = FALSE
!).
tibble(x = letters)
#> # A tibble: 26 × 1
#> x
#> <chr>
#> 1 a
#> 2 b
#> 3 c
#> 4 d
#> 5 e
#> 6 f
#> 7 g
#> 8 h
#> 9 i
#> 10 j
#> # … with 16 more rows
これにより、リスト列での利用が容易になる。
tibble(x = 1:3, y = list(1:5, 1:10, 1:20))
#> # A tibble: 3 × 2
#> x y
#> <int> <list>
#> 1 1 <int [5]>
#> 2 2 <int [10]>
#> 3 3 <int [20]>
リスト列は tidyr::nest()
で作成されることが多いが、手作業で作成するような場合に有効である。
変数名を調整することはない。
names(data.frame(`crazy name` = 1))
#> [1] "crazy.name"
names(tibble(`crazy name` = 1))
#> [1] "crazy name"
引数を遅延して順次評価する。
tibble(x = 1:5, y = x ^ 2)
#> # A tibble: 5 × 2
#> x y
#> <int> <dbl>
#> 1 1 1
#> 2 2 4
#> 3 3 9
#> 4 4 16
#> 5 5 25
row.names()
を使用することはない。 整頓されたデータの要点は、変数を一貫した方法で保存することである。 そのため、特殊な属性として変数を格納することはない。
長さ1のベクタのみをリサイクルしている。 これは、長さの大きなベクタをリサイクルすると、バグの原因になることが多いためである。
tibble()
を補完するために、tibble はオブジェクトを tibble に強制するための as_tibble()
を提供する。 一般に、as_tibble()
の方法は、as.data.frame()
の方法よりはるかに単純である。 リスト用のメソッドは、パフォーマンスを重視して書かれている。
<- replicate(26, sample(100), simplify = FALSE)
l names(l) <- letters
<- bench::mark(
timing 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 とデータフレームの主な違いは、表示、部分集合、リサイクルルールの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桁で表示され、末尾には分数成分の存在を示すドットが表示される。
オプションでデフォルトの外観を制御することができる。
options(pillar.print_max = n, pillar.print_min = m)
: n
以上の行がある場合、最初の m
行のみを表示す。 常にすべての行を表示す場合は、options(pillar.print_max = Inf)
を使用する。
options(pillar.width = n)
: n
の文字スロットを水平に使ってデータを表示す。n > getOption("width")
の場合、複数段になる。options(pillar.width = Inf)
を使用すると、画面の幅に関係なく、常に全列を表示す。
利用可能なオプションについては ?pillar::pillar_options
と ?tibble_options
を、型の省略形の概要については vignette("types")
を、数値の書式の詳細については vignette("numbers")
を、データフレーム表示との比較については vignette("digits")
を参照。
tibble は部分集合に対してかなり厳格である。 [
は常に別の tibble を返す。 データフレームとは対照的である。[
はデータフレームを返すこともあれば、単にベクタを返すこともある。
<- data.frame(x = 1:3, y = 3:1)
df1 class(df1[, 1:2])
#> [1] "data.frame"
class(df1[, 1])
#> [1] "integer"
<- tibble(x = 1:3, y = 3:1)
df2 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
を返す。
<- data.frame(abc = 1)
df $a
df#> [1] 1
<- tibble(abc = 1)
df2 $a
df2#> 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 への変換時や部分集合時に除去される。
<- data.frame(a = 1:3, row.names = letters[1:3])
df rownames(df)
#> [1] "a" "b" "c"
rownames(as_tibble(df))
#> [1] "1" "2" "3"
<- tibble(a = 1:3)
tbl 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 は全列の算術演算をサポートしない。 結果は黙ってデータフレームに強制される。 この動作は、今後のバージョンアップでエラーになる可能性があるので、当てにしないでみよう。
<- tibble(a = 1:3, b = 4:6)
tbl * 2
tbl #> a b
#> 1 2 8
#> 2 4 10
#> 3 6 12