Controlling display of numbers

tibble は、デフォルトで有効数字3桁で表示し、使用可能なスペースが小さすぎる場合は科学的記法に切り替える。 下線は、3桁の数字のグループを強調するために使用する。 この表示は、データフレームのデフォルト表示とは異なる。この違いの概要については、vignette("digits") を参照。 このディスプレイは多くの場合、有効であるが、すべてのユースケースで有効というわけではない。

library(tibble )

オプション

tibble 内の数値やその他のデータの表示をカスタマイズする最も簡単な方法は、オプションを定義することである。 包括的な概要については、?pillar::pillar_options を参照。

tibble (x = 123.4567)
#> # A tibble: 1 × 1
#>       x
#>   <dbl>
#> 1  123.
old <- options(pillar.sigfig = 7)
tibble (x = 123.4567)
#> # A tibble: 1 × 1
#>          x
#>      <dbl>
#> 1 123.4567
# Restore old options, see also rlang::local_options() for a more elegant way
options(old)

これにより、すべての列の表示が変更される。 列単位で表示オプションを指定する方法については、こちらを参照。

列ごとの番号の書式設定

新しいコンストラクタ num() では、数値のように振る舞うベクタを作成できるが、その表示をカスタマイズすることができる。 以下にいくつかの例を示すが、包括的な概要については、?num を参照。 同様に、char()、文字列の表示をカスタマイズすることができる。

num(-1:3, notation = "sci")
#> <pillar_num(sci)[5]>
#> [1] -1e0  0    1e0  2e0  3e0
tibble (
  x4 = num(8:12 * 100 + 0.5, digits = 4),
  x1 = num(8:12 * 100 + 0.5, digits = -1),
  usd = num(8:12 * 100 + 0.5, digits = 2, label = "USD"),
  percent = num(8:12 / 100 + 0.0005, label = "%", scale = 100),
  eng = num(10^(-3:1), notation = "eng", fixed_exponent = -Inf),
  si = num(10^(-3:1) * 123, notation = "si"),
  char = char(paste(LETTERS, collapse = " "), shorten = "mid")
)
#> # A tibble: 5 × 7
#>          x4       x1     usd percent   eng      si char                         
#>   <num:.4!> <num:.1>     USD       % [e-3]    <si> <char>                       
#> 1  800.5000    800.5  800.50    8.05     1 123   m A B C D E F G … T U V W X Y Z
#> 2  900.5000    900.5  900.50    9.05    10   1.23  A B C D E F G … T U V W X Y Z
#> 3 1000.5000   1000.5 1000.50   10.0    100  12.3   A B C D E F G … T U V W X Y Z
#> 4 1100.5000   1100.5 1100.50   11.0   1000 123     A B C D E F G … T U V W X Y Z
#> 5 1200.5000   1200.5 1200.50   12.0  10000   1.23k A B C D E F G … T U V W X Y Z

tibble の表示を担当するピラーパッケージは、数字の表示を正しくしようと努力しているが、すべてのユースケースに対応することは不可能である。 デフォルトの書式がアプリケーションに合わない場合、num() または char() を使って、個々の列の書式を再定義することができる。 このフォーマットは、ほとんどのデータ変換に耐えることができる。

ルールベースの数値書式

現在は、列ごとに手作業で書式を適用する必要がある。 以下のパターンは、 tibble のすべての列、または名前に基づいたいくつかの列に対して、一貫してこれを行うのに役立つだろう。

library(dplyr, warn.conflicts = FALSE)

markets <-
  as_tibble (EuStockMarkets) %>%
  mutate(time = time(EuStockMarkets), .before = 1)

markets
#> # A tibble: 1,860 × 5
#>     time   DAX   SMI   CAC  FTSE
#>    <dbl> <dbl> <dbl> <dbl> <dbl>
#>  1 1991. 1629. 1678. 1773. 2444.
#>  2 1992. 1614. 1688. 1750. 2460.
#>  3 1992. 1607. 1679. 1718  2448.
#>  4 1992. 1621. 1684. 1708. 2470.
#>  5 1992. 1618. 1687. 1723. 2485.
#>  6 1992. 1611. 1672. 1714. 2467.
#>  7 1992. 1631. 1683. 1734. 2488.
#>  8 1992. 1640. 1704. 1757. 2508.
#>  9 1992. 1635. 1698. 1754  2510.
#> 10 1992. 1646. 1716. 1754. 2497.
#> # … with 1,850 more rows
markets %>%
  mutate(across(-time, num, digits = 3))
#> # A tibble: 1,860 × 5
#>     time       DAX       SMI       CAC      FTSE
#>    <dbl> <num:.3!> <num:.3!> <num:.3!> <num:.3!>
#>  1 1991.  1628.750  1678.100  1772.800  2443.600
#>  2 1992.  1613.630  1688.500  1750.500  2460.200
#>  3 1992.  1606.510  1678.600  1718.000  2448.200
#>  4 1992.  1621.040  1684.100  1708.100  2470.400
#>  5 1992.  1618.160  1686.600  1723.100  2484.700
#>  6 1992.  1610.610  1671.600  1714.300  2466.800
#>  7 1992.  1630.750  1682.900  1734.500  2487.900
#>  8 1992.  1640.170  1703.600  1757.400  2508.400
#>  9 1992.  1635.470  1697.500  1754.000  2510.500
#> 10 1992.  1645.890  1716.300  1754.300  2497.400
#> # … with 1,850 more rows

num の計算 {#computing-on-num}

数値の書式設定は、結果のプレゼンテーションに有効である。 解析の早い段階で定義しておけば、フォーマットオプションはほとんどの操作で生き残る。 分析の初期段階で、データに適した出力オプションを定義しておくと、分析中にフォーマットの恩恵を受けることができる。 このフォーマットを最終的なプレゼンテーション(プロット、表、…)にシームレスに適用できるように取り組んでいる。

算数・数学

num() で作成された数値に算術演算を施す場合、その結果は最初の num オブジェクトのフォーマットを継承する。

num(1) + 2
#> <pillar_num[1]>
#> [1] 3
1 + num(2)
#> <pillar_num[1]>
#> [1] 3
1L + num(2)
#> <pillar_num[1]>
#> [1] 3
num(3.23456, sigfig = 4) - num(2)
#> <pillar_num:4[1]>
#> [1] 1.235
num(4, sigfig = 2) * num(3, digits = 2)
#> <pillar_num:2[1]>
#> [1] 12
num(3, digits = 2) * num(4, sigfig = 2)
#> <pillar_num:.2![1]>
#> [1] 12.00
-num(2)
#> <pillar_num[1]>
#> [1] -2

数学

同様に、数学演算についても、書式が継承される。

min(num(1:3, label = "$"))
#> <pillar_num{$}[1]>
#> [1] 1
mean(num(1:3, notation = "eng"))
#> <pillar_num(eng)[1]>
#> [1] 2e0
sin(num(1:3, label = "%", scale = 100))
#> <pillar_num{%}*100[3]>
#> [1] 84.1 90.9 14.1

オーバーライド

場合によっては、変換後に理想的なフォーマットが変更されることがある。 num() を繰り返し適用することができ、最後に設定したものが優先される。

num(1:3 + 0.125, digits = 4)
#> <pillar_num:.4![3]>
#> [1] 1.1250 2.1250 3.1250
transf <- 10 ^ num(1:3 + 0.125, digits = 4)
transf
#> <pillar_num:.4![3]>
#> [1]   13.3352  133.3521 1333.5214
num(transf, sigfig = 3)
#> <pillar_num:3[3]>
#> [1]   13.3  133.  1334.

回復

var() 関数は、書式が失われる例の一つである。

x <- num(c(1, 2, 4), notation = "eng")
var(x)
#> [1] 2.333333

median() 関数はもっとひどくて、num() のオブジェクトに対して壊れる。

median(x)
#> Error in `stop_vctrs()`:
#> ! `median.pillar_num()` not implemented.

その結果に num()、リカバリーするのも一つの方法である。

num(var(x), notation = "eng")
#> <pillar_num(eng)[1]>
#> [1] 2.33e0
num(median(as.numeric(x)), notation = "eng")
#> <pillar_num(eng)[1]>
#> [1] 2e0

自動回復のために、独自のバージョン var() を定義することもできるし、基本的な実装を上書きすることもできる。 なお、このパターンはまだ実験的なものであり、変更される可能性がある。

var_ <- function(x, ...) {
  out <- var(vctrs::vec_proxy(x), ...)
  vctrs::vec_restore(out, x)
}
var_(x)
#> <pillar_num(eng)[1]>
#> [1] 2.33e0

このパターンは、フォーマットを失うすべての関数に適用することができる。 以下に定義する make_restore() 関数は、関数を消費して派生関数を返す関数ファクトリである。

make_restore <- function(fun) {
  force(fun)
  function(x, ...) {
    out <- fun(vctrs::vec_proxy(x), ...)
    vctrs::vec_restore(out, x)
  }
}

var_ <- make_restore(var)
sd_ <- make_restore(sd)

var_(x)
#> <pillar_num(eng)[1]>
#> [1] 2.33e0
sd_(x)
#> <pillar_num(eng)[1]>
#> [1] 1.53e0