dplyr — 高速data.frame処理
data.frameに対して抽出(select, filter)、部分的変更(mutate)、要約(summarize)、ソート(arrange)などの処理を施すためのパッケージ。 前作plyrのうちdata.frameに関する部分が強化されている。 purrr や tidyr と一緒に使うとよい。
tidyverse に含まれているので、
install.packages("tidyverse")
で一括インストール、
library(tidyverse)
で一括ロード。
パイプ演算子 |> による関数の連結
x |> f(a, b)
は f(x, a, b)
と等価。
左の値 x
を第一引数として右の関数 f()
に渡す。
一時変数を作ったり、関数を何重にも重ねたりすることなく、
適用する順に次々と処理を記述することができるようになる。
慣れれば書きやすく読みやすい。
library(conflicted)
library(tidyverse)
result = diamonds |> # 生データから出発して
dplyr::select(carat, cut, price) |> # 列を抽出して
dplyr::filter(carat > 1) |> # 行を抽出して
dplyr::group_by(cut) |> # グループ化して
dplyr::summarize(mean(price)) |> # 平均を計算
print() # 表示してみる
cut mean(price)
1 Fair 7177.856
2 Good 7753.601
3 Very Good 8340.549
4 Premium 8487.249
5 Ideal 8674.227
同じことをパイプなしでやると読みにくい:
## with a temporary variable
result = dplyr::select(diamonds, carat, cut, price) # 列を抽出して
result = dplyr::filter(result, carat > 1) # 行を抽出して
result = dplyr::group_by(result, cut) # グループ化して
result = dplyr::summarize(result, mean(price)) # 平均を計算
## with nested functions
result = dplyr::summarize( # 平均を計算
dplyr::group_by( # グループ化して
dplyr::filter( # 行を抽出して
dplyr::select(diamonds, carat, cut, price), # 列を抽出して
carat > 1), # 行を抽出して
cut), # グループ化して
mean(price)) # 平均を計算
R 4.1 から標準で |>
が使えるようになり、徐々に普及してきた。
それまでdplyr始めtidyverseでは
magrittr の %>%
が長らく使われていた。
R 4.2 の段階では |>
のプレースホルダー _
の使い勝手がイマイチなので、
%>%
から完全移行できる状態ではない。
さらに高性能なものを求める人々は
pipeR
パッケージの %>>%
を使っていたが最近はあまり見かけない。
抽出・絞り込み
列
dplyr::select(.data, ...)
- 列を絞る。
:
範囲指定、!
負の指定が可能。 selection helpers によるパターン指定も便利。 複数の条件を組み合わせるには&
(AND),|
(OR) で。 残るのが1列だけでも勝手にvectorにはならずdata.frameのまま。diamonds |> dplyr::select(1, 2, 7) diamonds |> dplyr::select(carat, cut, price) diamonds |> dplyr::select(c("carat", "cut", "price")) diamonds |> dplyr::select(!c(carat, cut, price)) diamonds |> dplyr::select(starts_with("c")) diamonds |> dplyr::select(where(is.numeric)) # diamonds |> dplyr::select(-carat, -cut, -price)
カンマ区切りはORの意味で働くはずだがマイナス指定
dplyr::select(-carat, -cut, -price)
の場合だけANDのように働く(つまり3列とも抜ける)ので特殊。 (だからマニュアルから消えたのかな?) -
文字列ベクタで指定しようとすると意図が曖昧になるので、 ヘルパー関数
all_of()
,any_of()
を挟む。あるいは {{embrace}}, !!unquoting, pronoun$を使う:clarity = c("carat", "cut", "price") diamonds |> dplyr::select(clarity) # ambiguous! diamonds |> dplyr::select(.data$clarity) # clarity diamonds |> dplyr::select(all_of(clarity)) # carat, cut, price diamonds |> dplyr::select(any_of(clarity)) # carat, cut, price diamonds |> dplyr::select({{clarity}}) # carat, cut, price diamonds |> dplyr::select(!!clarity) # carat, cut, price diamonds |> dplyr::select(!!!rlang::syms(clarity)) # carat, cut, price
これらの指定方法は
rename()
やpull()
でも有効。一方、文字列を受け取れない
distinct()
やgroup_by()
などの関数には普通のunquoteは通用しない。 最後の例のようにrlang::data_syms()
でシンボルのリストを作って !!!unquote-splicing して渡す必要がある。columns = c("cut", "color") diamonds |> distinct(!!as.name(columns[1L])) diamonds |> distinct(!!!rlang::data_syms(columns))
詳しくは rlangパッケージのドキュメント か 宇宙船本第3章のコラム 「selectのセマンティクスとmutateのセマンティクス」を参照。
dplyr::pull(.data, var = -1, name = NULL)
- 指定した1列をvector(またはlist)としてdata.frameから抜き出す。
diamonds |> head() |> dplyr::pull(price) diamonds |> head() |> dplyr::pull("price") diamonds |> head() |> dplyr::pull(7) diamonds |> head() |> dplyr::pull(-4) diamonds |> head() %>% `[[`("price") diamonds |> head() %>% {.[["price"]]}
name
オプションにID的な列を渡すと名前付きvectorを楽に作れる:starwars |> dplyr::pull(mass, name)
行
dplyr::filter(.data, ..., .by = NULL, .preserve = FALSE)
- 条件を満たす行だけを返す。
base::subset()
と似たようなもの。diamonds |> dplyr::filter(carat > 3 & price < 10000)
carat cut color clarity depth table price x y z 1 3.01 Premium I I1 62.7 58 8040 9.10 8.97 5.67 2 3.11 Fair J I1 65.9 57 9823 9.15 9.02 5.98 3 3.01 Premium F I1 62.2 56 9925 9.24 9.13 5.73
評価結果が
NA
となる行は除去される。 特に不等号を使うときやや直感に反するので要注意。 e.g.,filter(gene != "TP53")
-
複数列で条件指定するには
if_any()
,if_all()
が使える。diamonds |> dplyr::filter(if_any(c(x, y, z), \(v) v > 20))
carat cut color clarity depth table price x y z 1 2.00 Premium H SI2 58.9 57.0 12210 8.09 58.90 8.06 2 0.51 Very Good E VS1 61.8 54.7 1970 5.12 5.15 31.80 3 0.51 Ideal E VS1 61.8 55.0 2075 5.15 31.80 5.12
diamonds |> dplyr::filter(if_all(where(is.numeric), \(x) x > 4.1))
carat cut color clarity depth table price x y z 1 4.13 Fair H I1 64.8 61 17329 10.00 9.85 6.43 2 5.01 Fair J I1 65.5 59 18018 10.74 10.54 6.98 3 4.50 Fair J I1 65.8 58 18531 10.23 10.16 6.72
dplyr::distinct(.data, ..., .keep_all = FALSE)
- 指定した列に関してユニークな行のみ返す。
base::unique.data.frame()
よりも高速で、filter(!duplicated(.[, ...]))
よりスマートで柔軟。 指定しなかった列を残すには.keep_all = TRUE
とする。diamonds |> dplyr::distinct(cut)
cut 1 Ideal 2 Premium 3 Good 4 Very Good 5 Fair
dplyr::slice(.data, ..., .by = NULL, .preserve = FALSE)
- 行番号を指定して行を絞る。
`[`(i,)
の代わりに。diamonds |> dplyr::slice(1, 2, 3)
carat cut color clarity depth table price x y z 1 0.23 Ideal E SI2 61.5 55 326 3.95 3.98 2.43 2 0.21 Premium E SI1 59.8 61 326 3.89 3.84 2.31 3 0.23 Good E VS1 56.9 65 327 4.05 4.07 2.31
dplyr::slice_head(.data, ..., n, prop)
,slice_tail()
- 先頭・末尾の行を抽出。
dplyr::slice_max(.data, order_by, ..., n, prop, by = NULL, with_ties = TRUE, na_rm = FALSE)
order_by, ...
で指定した列の降順でn
行だけ返す。 境界のタイを保持する場合はn
行以上の出力になる。 昇順で取りたいときはマイナス指定かslice_min()
。dplyr::slice_sample(.data, ..., n, prop, weight_by = NULL, replace = FALSE)
- 指定した行数・割合だけランダムサンプルする。
列の変更・追加
dplyr::mutate(.data, ..., .by = NULL, .keep = "all", .before = NULL, .after = NULL)
- 新しい列を作ったり、既存の列を変更したり。
base::transform()
の改良版。diamonds |> dplyr::mutate(gram = 0.2 * carat) |> # create new dplyr::mutate(price = price * 140) # modify existing
carat cut color clarity depth table price x y z gram 1 0.23 Ideal E SI2 61.5 55 45640 3.95 3.98 2.43 0.046 2 0.21 Premium E SI1 59.8 61 45640 3.89 3.84 2.31 0.042 -- 53939 0.86 Premium H SI2 61.0 58 385980 6.15 6.12 3.74 0.172 53940 0.75 Ideal D SI2 62.2 55 385980 5.83 5.87 3.64 0.150
- 変数に入った文字列を列名として使いたい場合は上記
select()
のときと同様、 {{embrace}} や !!unquote を使う。A = "carat" B = "gram" diamonds |> dplyr::mutate(B = 0.2 * !!as.name(A))
carat cut color clarity depth table price x y z B 1 0.23 Ideal E SI2 61.5 55 326 3.95 3.98 2.43 0.046 2 0.21 Premium E SI1 59.8 61 326 3.89 3.84 2.31 0.042 -- 53939 0.86 Premium H SI2 61.0 58 2757 6.15 6.12 3.74 0.172 53940 0.75 Ideal D SI2 62.2 55 2757 5.83 5.87 3.64 0.150
- 左辺(代入先)の名前も文字列を使って表現したい場合は
walrus(セイウチ)演算子
:=
を使う:diamonds |> dplyr::mutate({{B}} := 0.2 * !!as.name(A))
carat cut color clarity depth table price x y z gram 1 0.23 Ideal E SI2 61.5 55 326 3.95 3.98 2.43 0.046 2 0.21 Premium E SI1 59.8 61 326 3.89 3.84 2.31 0.042 -- 53939 0.86 Premium H SI2 61.0 58 2757 6.15 6.12 3.74 0.172 53940 0.75 Ideal D SI2 62.2 55 2757 5.83 5.87 3.64 0.150
.keep = "all"
: すべての列を残すデフォルト。.keep = "used"
: 入力に使った列と出力の列のみ残す。.keep = "unused"
: 入力に使った列は捨て、出力の列とほかの列を残す。.keep = "none"
: グループ化と出力の列のみ残す。旧transmute()
のような挙動。
- 新しい列をどこに作るかを
.before
,.after
指定できる。 -
複数の列をtidyselectして1列作りたいときは
dplyr::pick(...)
とReduce(f, x)
/purrr::reduce(.x, .f)
を組み合わせる:diamonds |> dplyr::mutate(prod = Reduce(`*`, pick(where(is.numeric)))) |> dplyr::mutate(mean_xyz = Reduce(`+`, pick(x:z)) / ncol(pick(x:z))) |> dplyr::mutate(max_xyz = Reduce(pmax, pick(x:z))) |> print()
dplyr::select()
と違って.data
を渡さなくてもいいので、 プレースホルダの貧弱な base pipe|>
でも使える。 dplyr::rename(.data, ...)
- 列の改名。
mutate()
と同じようなイメージでnew = old
と指定。diamonds |> dplyr::rename(SIZE = carat)
SIZE cut color clarity depth table price x y z 1 0.23 Ideal E SI2 61.5 55 326 3.95 3.98 2.43 2 0.21 Premium E SI1 59.8 61 326 3.89 3.84 2.31 -- 53939 0.86 Premium H SI2 61.0 58 2757 6.15 6.12 3.74 53940 0.75 Ideal D SI2 62.2 55 2757 5.83 5.87 3.64
- 変数に入った文字列を使う場合も
mutate()
と同様に {{embrace}} や !!unquote で:old_name = "carat" new_name = toupper(old_name) diamonds |> dplyr::rename({{new_name}} := {{old_name}})
CARAT cut color clarity depth table price x y z 1 0.23 Ideal E SI2 61.5 55 326 3.95 3.98 2.43 2 0.21 Premium E SI1 59.8 61 326 3.89 3.84 2.31 -- 53939 0.86 Premium H SI2 61.0 58 2757 6.15 6.12 3.74 53940 0.75 Ideal D SI2 62.2 55 2757 5.83 5.87 3.64
名前付きベクターと !!!unquote-splicing を使えば一括指定できる:
named_vec = setNames(names(diamonds), LETTERS[seq(1, 10)]) diamonds |> dplyr::rename(!!!named_vec)
A B C D E F G H I J 1 0.23 Ideal E SI2 61.5 55 326 3.95 3.98 2.43 2 0.21 Premium E SI1 59.8 61 326 3.89 3.84 2.31 -- 53939 0.86 Premium H SI2 61.0 58 2757 6.15 6.12 3.74 53940 0.75 Ideal D SI2 62.2 55 2757 5.83 5.87 3.64
rename_with(.tbl, .fn, .cols = everything(), ...)
はリネーム関数を渡せる亜種:diamonds |> dplyr::rename_with(toupper, everything())
data.frameの要約・集計・整列
dplyr::summarize(.data, ..., .by = NULL, .group = NULL)
- 指定した列に関数を適用して1行のdata.frameにまとめる。
グループ化されていたらグループごとに適用して
bind_rows()
する。diamonds |> group_by(cut) |> summarize(avg_carat = mean(carat), max_price = max(price))
cut avg_carat max_price 1 Fair 1.0461366 18574 2 Good 0.8491847 18788 3 Very Good 0.8063814 18818 4 Premium 0.8919549 18823 5 Ideal 0.7028370 18806
-
複数カラムに関数を適用するには
across()
を使う:# summarize_at diamonds |> summarize(across(starts_with("c"), max), .by = cut) # summarize_if diamonds |> summarize(across(where(is.numeric), max), .by = cut) # summarize_all diamonds |> summarize(across(everything(), max), .by = cut)
-
各列の計算結果は長さ1でなければいけない。 そうじゃなくても大丈夫な時期もあったが、その機能は
reframe()
に分離された。 dplyr::reframe(.data, ..., .by = NULL, .group = NULL)
- 各グループの結果が複数行にまたがっても大丈夫な
summarize()
亜種。diamonds |> dplyr::reframe(range(carat), range(price))
range(carat) range(price) 1 0.20 326 2 5.01 18823
-
各グループの結果がtibbleの場合、結合・展開してくれる:
diamonds |> dplyr::nest_by(cut) |> dplyr::reframe(head(data, 2L))
これを利用して複数ファイルを一気読みできる:
path = fs::dir_ls("path/to/data", glob = "*.tsv") df = tibble(path) |> dplyr::rowwise() |> dplyr::reframe(readr::read_tsv(path))
けどまあ
purrr::map(path, read_tsv) |> purrr::list_rbind()
のほうが読みやすい気がする。 dplyr::tally(x, wt, sort = FALSE)
summarize(x, n = n())
のショートカット。wt
にカラムを指定して重み付けすることもできる。dplyr::add_tally()
は元の形を維持したままカウント列を追加。dplyr::count(x, ..., wt = NULL, sort = FALSE)
group_by(...) |> tally()
のショートカット。dplyr::add_count()
は元の形を維持したままカウント列を追加。dplyr::arrange(.data, ..., .by_group = FALSE)
- 指定した列の昇順でdata.frameの行を並べ替える。
arrange(desc(column))
で降順になる。order()
を使うよりもタイピングの繰り返しが少ないし直感的mtcars[order(mtcars$cyl, mtcars$disp), ] # is equivalent to mtcars |> dplyr::arrange(cyl, disp)
dplyr::relocate(.data, ..., .before = NULL, .after = NULL)
- 指定した列を左端(もしくは
.before
/.after
別の列)に移動する。
data.frameを結合
dplyr::***_join(x, y, by = NULL, copy = FALSE)
by
で指定した列がマッチするように行を合わせてcbind()
full_join()
:x
とy
の全ての行を保持。
inner_join()
:x
とy
のby
がマッチする行のみ
left_join()
:x
の全ての行を保持。y
に複数マッチする行があったらすべて保持。
right_join()
:y
の全ての行を保持。x
に複数マッチする行があったらすべて保持。
semi_join()
:x
の全ての行を保持。y
に複数マッチする行があっても元のx
の行だけ保持。
anti_join()
:y
にマッチしないx
の行のみ。
cross_join()
: マッチするものではなく、全ての組み合わせを作って結合。-
列名が異なる場合は
by
を名前付きvectorにする:dplyr::full_join(band_members, band_instruments2, by = c(name = "artist"))
join_by()
を使えば不等号などを含めて柔軟に結合条件を指定できる。dplyr::bind_rows(...)
,dplyr::bind_cols(...)
- 標準の
rbind()
,cbind()
より効率よくdata.frameを結合。 引数は個別でもリストでもよい。 そのほかにも標準の集合関数を置き換えるものが提供されている:intersect()
,union()
,union_all()
,setdiff()
,setequal()
その他の関数
主にmutate()
やfilter()
を補助するもの
dplyr::if_else(condition, true, false, missing = NULL)
- 標準の
ifelse()
よりも型に厳しく、高速らしい。 NAのときにどうするかを指定できるのも大変良い。 ネストせずにスッキリ書けるdplyr::case_when()
も便利。 dplyr::coalesce(x, ...)
- 最初のvectorでNAだったとこは次のvectorのやつを採用、
という
ifelse(!is.na(x), x, y)
的な処理をする。 基本的には同じ長さのvectorを渡すが、 2つめに長さ1のを渡してtidyr::replace_na()
的に使うのも便利。 dplyr::na_if(x, y)
x[x == y] = NA; x
のショートカットdplyr::recode(.x, ..., .default = NULL, .missing = NULL)
- vectorの値を変更する。e.g.,
recode(letters, a = "A!", c = "C!")
dplyr::row_number(x)
rank(x, ties.method = "first", na.last = "keep")
のショートカット。 グループ毎に連番を振るのに便利。同点でも登場順に違う順位を与える。dplyr::min_rank(x)
: 同点には同じ値。2位タイがあれば3位不在。ties.method = "min"
dplyr::dense_rank(x)
: 同点には同じ値。2位タイがあっても3位から再スタート。dplyr::consecutive_id(...)
- 値が変化したら番号をインクリメント。こういうグループ化したいときがある:
c(0, 0, 1, 1, 1, 0, 0, 1) |> dplyr::consecutive_id()
[1] 1 1 2 2 2 3 3 4
dplyr::ntile(x, n)
- 数値ベクトル
x
を順位によってn
個のクラスに均等分け dplyr::n_distinct(x)
- 高速で簡潔な
length(unique(x))
dplyr::n_groups(x)
- グループ数。
dplyr::last(x, order_by = NULL, default = default_missing(x))
- 最後の要素にアクセス。
x[length(x)]
やtail(x, 1)
よりも楽チンだが、 安全性重視のdplyr::nth()
を内部で呼び出すため遅い。 dplyr::lead(x n = 1, default = NA, order_by = NULL)
,dplyr::lag(...)
x
の中身をn
だけずらしてdefault
で埋める。lead()
は前に、lag()
は後ろにずらすlag(seq_len(5), 2)
[1] NA NA 1 2 3
## [1] NA NA 1 2 3
dplyr::between(x, left, right)
left <= x & x <= right
のショートカット。dplyr::near(x, y, tol = .Machine$double.eps^0.5)
abs(x - y) < tol
のショートカット。dplyr::case_when(...)
if {} else if {} else if {} ...
のショートカット。
グループ化
tidyr
でネストして、
purrr
でその list of data.frames に処理を施し、
dplyr
でその変更を元の data.frame に適用する、
というのがtidyverse流の柔軟なやり方。
v0.8.1で group_modify()
などが導入され、
ネストせずグループ化までで済ませやすくなった。
v1.1.0 からは多くの関数に一時グループ化
.by
/ by
オプションが追加され、
事前のグループ化と事後のグループ解除を省略しやすくなった。
diamonds |>
dplyr::group_nest(cut) |>
dplyr::mutate(data = purrr::map(data, \(x) head(x, n = 2L))) |>
tidyr::unnest()
# dplyr >= 0.8.1
diamonds |>
dplyr::group_by(cut) |>
dplyr::group_modify(\(x, key) head(x, 2L)) |>
dplyr::ungroup()
# dplyr >= 1.1.0
diamonds |>
dplyr::slice_head(n = 2L, by = cut)
dplyr::group_by(.data, ..., add = FALSE, .drop = group_by_drop_default(.data))
- グループごとに区切って次の処理に渡す。
e.g.
summarize()
,slice()
,tally()
,group_modify()
など .drop = FALSE
とすると行数ゼロになるグループも捨てずに保持できる。dplyr::group_data(.data)
- グループ情報を参照:
diamonds |> dplyr::group_by(cut) |> dplyr::group_data()
cut .rows 1 Fair <int [1610]> 2 Good <int [4906]> 3 Very Good <int [12082]> 4 Premium <int [13791]> 5 Ideal <int [21551]>
左側のキー列だけ欲しければ
dplyr::group_keys()
、
左端の行番号だけ欲しければdplyr::group_rows()
。 dplyr::group_nest(.tbl, ..., .key = "data", keep = FALSE)
- 入れ子 data.frame を作る。
tidyr::nest(.by = c(...))
と役割が被りすぎて微妙な立場らしい。 keep = TRUE
とするとグループ化に使った列も入れ子のdata.frameに残す。- グループ化を解除してフラットな
tbl_df
を返す。 dplyr::nest_by(.tbl, ..., .key = "data", keep = FALSE)
- 上記
group_nest
とほぼ同じだが、こちらはグループ化されたままrowwise_df
を返す。 dplyr::group_split(.tbl, ..., .key = "data", .keep = FALSE)
- list of data.frames に分割する。
.tbl |> split(.$group)
と同等だが、 ドットダラーを使わくて済むし複数列をキーにするのも簡単。 dplyr::group_indices(.data, ...)
grouped_df
ではなくグループIDとして1からの整数列を返す版group_by()
dplyr::group_modify(.tbl, .f, ..., .keep = FALSE)
- グループごとに
.f
を適用して再結合したdata.frameを返す。 .f
は2つの引数をとる関数。 1つめは区切られたdata.frame、 2つめはグループ化のキー(となった列を含む1行のdata.frame)。 引数が1つだったり、違うものを2つめに受け取る関数はそのままじゃ渡せないので、 purrrのときと同様に無名関数に包んで渡す。diamonds |> dplyr::group_by(cut) |> dplyr::group_modify(\(x, key) head(x, 2L))
cut carat color clarity depth table price x y z 1 Fair 0.22 E VS2 65.1 61 337 3.87 3.78 2.49 2 Fair 0.86 E SI2 55.1 69 2757 6.45 6.33 3.52 3 Good 0.23 E VS1 56.9 65 327 4.05 4.07 2.31 4 Good 0.31 J SI2 63.3 58 335 4.34 4.35 2.75 -- 7 Premium 0.21 E SI1 59.8 61 326 3.89 3.84 2.31 8 Premium 0.29 I VS2 62.4 58 334 4.20 4.23 2.63 9 Ideal 0.23 E SI2 61.5 55 326 3.95 3.98 2.43 10 Ideal 0.23 J VS1 62.8 56 340 3.93 3.90 2.46
-
group_map()
は結果をbind_rows()
せずlistとして返す亜種。
group_walk()
は.f
適用前の.tbl
を返す亜種。 dplyr::rowwise(data, ...)
- 受け取ったdataに
rowwise_df
クラスを付与して返す。 これは1行ごとにグループ化されたgrouped_df
のようなもので、 mutate などを適用すると列全体ではなく1行ごとに関数に渡される。 一旦非推奨となったがv1.0.0で蘇った。 - ループ処理が重いので、計算内容と行数のバランスに注意。
例えば
dplyr::c_across()
の併用で横方向の合計や平均を簡潔に書けるが、 ベクトル演算を使う場合に比べてかなり遅い。diamonds |> dplyr::rowwise() |> dplyr::mutate(mean_xyz = mean(c_across(x:z))) # slow diamonds |> dplyr::mutate(mean_xyz = Reduce(`+`, pick(x:z)) / ncol(pick(x:z))) # fast
deprecated/superseded
dplyr::do(.data, ...)
reframe()
,slice*()
などに取って代わられた。diamonds |> dplyr::group_by(cut) |> dplyr::do(head(., 2L)) diamonds |> dplyr::slice_head(n = 2L, by = cut) diamonds |> dplyr::reframe(across(everything(), range), .by = cut)
dplyr::transmute(.data, ...)
- 指定した列以外を保持しない版
mutate()
。 言い換えると、列の中身の変更もできる版select()
。 mutate(.keep = "none")
に取って代わられた。*_at()
,*_if()
,*_all()
,*_each()
- 条件を満たす列・複数の列に関数を適用する
mutate()
,summarize()
亜種。across()
の登場により非推奨。 top_n()
,top_frac()
slice_min()
,slice_max()
に取って代わられた。sample_n()
,sample_frac()
slice_sample()
に取って代わられた。
matrix, array
data.frame を主眼とする dplyr では matrix や array を扱わない。
一時期存在していた tbl_cube
関連の機能は
cubelyr に隔離された。
as.tbl_cube(x, dim_names, met_names, ...)
- matrix/arrayからdata.frameの一歩手前に変換する。
reshape2::melt
の改良版。 これの結果にtibble::as_tibble()
を適用するとわかりやすい。 - ただし
dimnames(x)
が空ではダメで、長さの正しい名前付きlistになっている必要がある。
# deprecated
iris3 |>
reshape2::melt() |>
tibble::as_tibble() |>
dplyr::rename(obs = Var1, metrics = Var2, species = Var3)
# new
x = iris3
dimnames(x)[[1L]] = seq_len(dim(iris3)[[1L]])
names(dimnames(x)) = c("obs", "metrics", "species")
cubelyr::as.tbl_cube(x, met_name = "value") |> as_tibble()