[解決済み】data.table vs dplyr:一方がうまくできない、またはうまくできないことを行うことができますか?
質問
概要
比較的馴染みのある
data.table
とはあまり関係ありません。
dplyr
. 私は、いくつかの
dplyr
ヴィネット
やSOで出てきた例などを参考に、今のところ私の結論はこうです。
-
data.table
とdplyr
は、グループ数が多い場合(>10-10万)や、その他の状況(以下のベンチマークを参照)を除いて、速度が同等です。 -
dplyr
は、よりアクセスしやすいシンタックスです。 -
dplyr
潜在的なDBとの相互作用を抽象化する(またはする) - 細かい機能の違いがあります(下記の「例/使い方」を参照)
私の中では、2.はかなり使い慣れたものなので、あまり重要視していません。
data.table
しかし、初めて両者を使うユーザーにとっては大きな要素になることは理解しています。 どちらがより直感的か、という議論は、すでにこの製品に慣れている人の立場からの質問とは無関係なので、避けたいと思います。
data.table
. また、quot;more intuitive" leads the faster analysisという議論も避けたいと思います(確かにそうですが、ここでも私が最も興味があるのはそこではありません)。
質問
知りたいことは
- どちらのパッケージに慣れている人にとっても、どちらかのパッケージでコーディングする方がずっと簡単な分析タスクがありますか (必要なキーストロークと必要な難解さのレベルの組み合わせ。それぞれ少ない方が良い)。
- あるパッケージと別のパッケージの間で、実質的に(すなわち2倍以上)効率的に実行される分析タスクがあるかどうか。
一
最近のSO質問
というのも、それまで私は
dplyr
で既にできること以上のことを提供することはできません。
data.table
. 以下は
dplyr
の解答(Q末尾のデータ)です。
dat %.%
group_by(name, job) %.%
filter(job != "Boss" | year == min(year)) %.%
mutate(cumu_job2 = cumsum(job2))
という私のハッキングの試みよりはずっとましです。
data.table
を解決することができます。 とはいえ、良い
data.table
の解決策もかなり良いものです(Jean-Robert, Arunに感謝、ここで私は厳密な最適解よりも単一記述を好んだことに注意)。
setDT(dat)[,
.SD[job != "Boss" | year == min(year)][, cumjob := cumsum(job2)],
by=list(id, job)
]
後者の構文は非常に難解に見えるかもしれませんが、実は
data.table
(つまり、もっと難解なトリックを使わない)。
理想を言えば、このような良い例を見てみたいですね。
dplyr
または
data.table
の方が、実質的に簡潔で、性能も優れています。
例
使用方法-
dplyr
は、任意の数の行を返すグループ化された操作を許可しません ( eddiの質問 に実装されるようです。 dplyr 0.5 また、@beginneR は、以下のような回避策を示しています。do
を@eddiさんの質問への回答で紹介しています)。 -
data.table
サポート ローリングジョイン (@dholstius さんありがとうございます) と同様に オーバーラップジョイン -
data.table
という形の式を内部的に最適化します。DT[col == value]
またはDT[col %in% values]
に対して 速度 を通して 自動インデックス作成 を使用する バイナリサーチ と同じRの基本構文を使用しながら こちらをご覧ください には、より詳細な情報と小さなベンチマークがあります。 -
dplyr
は、関数の標準的な評価版(例えばregroup
,summarize_each_
のプログラム的な使用を簡素化することができます)。dplyr
(のプログラム的な使用に注意)。data.table
は間違いなく可能です。ただ、少なくとも私の知る限りでは、置換や引用など、いくつかの慎重な考慮が必要です)
-
を実行しました。
私自身のベンチマーク
で、両パッケージは、グループ数が非常に多い場合(100K)を除いて、quot;split apply combine"スタイルの分析で同等であることがわかりました。
data.table
が大幅に高速化されます。 -
Arunはいくつか走りました。
結合のベンチマーク
ということを示す。
data.table
よりも優れたスケールdplyr
は、グループ数の増加に伴って更新されます (両パッケージの最近の拡張とRの最近のバージョンで更新されました)。 また、ベンチマークを取得しようとしたときに 一意な値 があります。data.table
~6倍速 -
(未確認)には
data.table
大きなバージョンのグループ/適用/ソートで75%高速化しながらもdplyr
は小さいものでは40%も速かった( またもやコメントからSO質問 danasさん、ありがとうございます)。 -
のメイン作者であるMattは
data.table
を、持っています。 のグループ化操作のベンチマークを行いました。data.table
,dplyr
とパイソンpandas
最大20億行(RAMで100GB) . -
An
80Kグループに関する古いベンチマーク
があります。
data.table
~8倍速
データ
これは質問コーナーで紹介した最初の例に対するものです。
dat <- structure(list(id = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L,
2L, 2L, 2L, 2L, 2L, 2L), name = c("Jane", "Jane", "Jane", "Jane",
"Jane", "Jane", "Jane", "Jane", "Bob", "Bob", "Bob", "Bob", "Bob",
"Bob", "Bob", "Bob"), year = c(1980L, 1981L, 1982L, 1983L, 1984L,
1985L, 1986L, 1987L, 1985L, 1986L, 1987L, 1988L, 1989L, 1990L,
1991L, 1992L), job = c("Manager", "Manager", "Manager", "Manager",
"Manager", "Manager", "Boss", "Boss", "Manager", "Manager", "Manager",
"Boss", "Boss", "Boss", "Boss", "Boss"), job2 = c(1L, 1L, 1L,
1L, 1L, 1L, 0L, 0L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 0L)), .Names = c("id",
"name", "year", "job", "job2"), class = "data.frame", row.names = c(NA,
-16L))
解決方法は?
包括的な回答/比較を提供するためには、少なくとも以下の点をカバーする必要があります(重要度の順不同)。
Speed
,
Memory usage
,
Syntax
と
Features
.
私の意図は、data.tableの観点から、それぞれをできるだけ明確にカバーすることです。
<ブロッククオート注:明示的に言及されていない限り、dplyrを参照すると、内部がRcppを使用したC++であるdplyrのdata.frameインタフェースを参照することになります。
data.tableの構文は、その形式が統一されています -。
DT[i, j, by]
. このため
i
,
j
と
by
を一緒にするのは、デザイン上の理由です。関連する操作を一緒にしておくことで
最適化しやすい
のためのオペレーションを
スピード
といった、より重要な
メモリ使用量
を提供し、また、いくつかの
強力な機能
を、構文の一貫性を保ちつつ、実現しました。
1. 速度
かなりの数のベンチマーク(ただし、ほとんどはグループ化操作に関するもの)が、すでに質問に追加されている data.table get
より速く
グループ化するグループや行の数が増えるにつれ、dplyr よりも
マットによるベンチマーク
からのグループ化について
1,000万行~20億行
(RAMで100GB)で
1億~1,000万グループ
とグループ化カラムを変化させ、これも比較します。
pandas
. こちらもご覧ください
更新されたベンチマーク
を含む。
Spark
と
pydatatable
にも対応しています。
ベンチマークについては、こうした残された部分もカバーできるといいですね。
-
を含むグループ化操作 行のサブセット - すなわち
DT[x > val, sum(y), by = z]
型の演算を行う。 -
などの他の操作のベンチマークを行う。 更新 と ジョインズ .
-
また、ベンチマーク メモリフットプリント を、実行時間だけでなく、各操作に対して設定します。
2. メモリ使用量
-
以下の操作を含む
<ブロッククオートfilter()
またはslice()
はメモリ効率が悪いことがあります(data.framesとdata.tablesの両方で)。 この記事を見る .注意点 ハドレー氏のコメント について話しています。 スピード (彼にとってdplyrは十分速いということ)、一方、ここでの大きな関心事は メモリ .
-
data.table インターフェースでは、現時点では、カラムの変更/更新を行うことができます。 参照 (結果を変数に再代入する必要がないことに注意してください)。
# sub-assign by reference, updates 'y' in-place DT[x >= 1L, y := NA]
しかし、dplyr は決して は参照によって更新されます。dplyrに相当するのは、次のようになります(結果を再代入する必要があることに注意してください)。
# copies the entire 'y' column ans <- DF %>% mutate(y = replace(y, which(x >= 1L), NA))
これに対する懸念は 参照透過性 . data.tableオブジェクトを参照しながら更新することは、特に関数内では必ずしも望ましいことではありません。しかし、これは非常に便利な機能です。 これ と これ の投稿は、面白いケースを想定しています。そして、私たちはそれを維持したいのです。
そのため、輸出に向けた取り組みを行っています。
shallow()
を提供するdata.tableの関数です。 両方の可能性 . 例えば、関数内で入力のdata.tableを変更しないことが望ましい場合、次のようにすることができます。foo <- function(DT) { DT = shallow(DT) ## shallow copy DT DT[, newcol := 1L] ## does not affect the original DT DT[x > 2L, newcol := 2L] ## no need to copy (internally), as this column exists only in shallow copied DT DT[x > 2L, x := 3L] ## have to copy (like base R / dplyr does always); otherwise original DT will ## also get modified. }
を使用しないことで
shallow()
の場合、旧来の機能は維持されます。bar <- function(DT) { DT[, newcol := 1L] ## old behaviour, original DT gets updated by reference DT[x > 2L, x := 3L] ## old behaviour, update column x in original DT. }
を作成することで シャローコピー を使って
<ブロッククオートshallow()
しかし、元のオブジェクトを変更したくないという要望は理解できます。私たちは、あなたが変更した列をコピーすることを保証しながら、内部ですべてを処理します。 どうしても必要なときだけ . 実装すると、これで 参照透過性 の問題を完全に解決し、ユーザーに両方の可能性を提供します。また、一度
<ブロッククオートshallow()
がエクスポートされた場合、dplyrのdata.tableインタフェースはほとんどすべてのコピーを回避する必要があります。したがって、dplyrの構文を好む人は、data.tablesでそれを使用することができます。しかし、参照による(サブ)割り当てなど、data.tableが提供する多くの機能が欠けていることに変わりはないでしょう。
-
結合しながら集計する。
次のような2つのdata.tablesがあるとする。
DT1 = data.table(x=c(1,1,1,1,2,2,2,2), y=c("a", "a", "b", "b"), z=1:8, key=c("x", "y")) # x y z # 1: 1 a 1 # 2: 1 a 2 # 3: 1 b 3 # 4: 1 b 4 # 5: 2 a 5 # 6: 2 a 6 # 7: 2 b 7 # 8: 2 b 8 DT2 = data.table(x=1:2, y=c("a", "b"), mul=4:3, key=c("x", "y")) # x y mul # 1: 1 a 4 # 2: 2 b 3
そして、あなたが取得したいのは
sum(z) * mul
の各行に対してDT2
列で結合している間x,y
. どちらかです。-
-
アグリゲート
DT1
を取得する。sum(z)
2)結合を行い、3)乗算を行う(または)。data.tableの方法
DT1[, .(z = sum(z)), keyby = .(x,y)][DT2][, z := z*mul][].
dplyr相当
DF1 %>% group_by(x, y) %>% summarise(z = sum(z)) %>%。 right_join(DF2) %>% mutate(z = z * mul)
-
-
-
を使用して)一挙に行う。
by = .EACHI
機能)を使用します。DT1[DT2, list(z=sum(z) * mul), by = .EACHI]の場合。
-
メリットは何ですか?
-
中間結果のためにメモリーを確保する必要がない。
-
グループ化・ハッシュ化を2回行う必要がない(1回は集計用、もう1回は結合用)。
-
そして、さらに重要なことは、私たちが行いたかった操作が
j
の(2)にある。
確認 この記事 についての詳しい説明は
by = .EACHI
. 中間結果は生成されず、結合と集計はすべて一度に実行されます。をご覧ください。 これ , これ そして これ の投稿は、実際の利用シーンを想定しています。
で
dplyr
を指定する必要があります。 結合して集約するか、先に集約してから結合する。 どちらもメモリ(これはスピードにつながります)の点では効率的ではありません。 -
-
更新と結合。
以下に示すdata.tableのコードを考えてみましょう。
DT1[DT2, col := i.mul]
追加・更新
DT1
カラムcol
とmul
からDT2
のある行についてDT2
のキーカラムと一致するDT1
. のこの操作に正確に相当するものがあるとは思えません。dplyr
を回避することなく、すなわち*_join
をコピーしなければなりません。DT1
は、新しいカラムを追加するだけなので、不要です。確認 この記事 は、実際の使用シナリオをご覧ください。
要約すると、最適化の一つひとつが重要であることを認識することが重要です。例えば グレース・ホッパー は言うだろう。 ナノ秒を気にする !
3. シンタックス
では、次に シンタックス . ハドレーは次のようにコメントしています。 こちら :
データテーブルは非常に高速ですが、その簡潔さゆえに 学習しにくい と それを使用したコードは、書いた後に読むのが難しくなる ...
この発言は非常に主観的であるため、無意味だと思います。私たちが試せるのは、次のような対比です。 構文の一貫性 . data.tableとdplyrの構文を並べて比較してみます。
以下のようなダミーデータを使って作業します。
DT = data.table(x=1:10, y=11:20, z=rep(1:2, each=5))
DF = as.data.frame(DT)
-
基本的な集計・更新操作。
# case (a) DT[, sum(y), by = z] ## data.table syntax DF %>% group_by(z) %>% summarise(sum(y)) ## dplyr syntax DT[, y := cumsum(y), by = z] ans <- DF %>% group_by(z) %>% mutate(y = cumsum(y)) # case (b) DT[x > 2, sum(y), by = z] DF %>% filter(x>2) %>% group_by(z) %>% summarise(sum(y)) DT[x > 2, y := cumsum(y), by = z] ans <- DF %>% group_by(z) %>% mutate(y = replace(y, which(x > 2), cumsum(y))) # case (c) DT[, if(any(x > 5L)) y[1L]-y[2L] else y[2L], by = z] DF %>% group_by(z) %>% summarise(if (any(x > 5L)) y[1L] - y[2L] else y[2L]) DT[, if(any(x > 5L)) y[1L] - y[2L], by = z] DF %>% group_by(z) %>% filter(any(x > 5L)) %>% summarise(y[1L] - y[2L])
-
data.tableの構文はコンパクトで、dplyrの構文はかなり冗長です。(a)の場合とほぼ同じです。
-
(b)の場合、(c)のように
filter()
を使用し、dplyrでは 要約 . しかし、一方 更新 の中にロジックを移動させる必要がありました。mutate()
. しかし、data.table では、両方の操作を同じロジックで表現しています。x > 2
を取得しますが、最初のケースではsum(y)
一方、2 番目のケースでは、これらの行を更新してy
をその累積和で返す。というのは、このような意味です。
DT[i, j, by]
フォーム は一貫して . -
同様に(c)の場合、以下のようになります。
if-else
という条件では、論理的に表現することができます。 "as-is"。 をdata.tableとdplyrの両方で使用することができます。しかし、もしあなたがif
条件を満たし、そうでない場合はスキップされます。summarise()
を直接指定することができます(AFAICT)。私たちはfilter()
を最初に作成し、それからまとめる。summarise()
は常に 単一値 .同じ結果を返しますが
filter()
では、実際の操作を目立たなくしています。を使用することは大いにあり得ることです。
filter()
が、私が言いたいのは、そうする必要はないはずだということです。
-
-
複数カラムの集計・更新
# case (a) DT[, lapply(.SD, sum), by = z] ## data.table syntax DF %>% group_by(z) %>% summarise_each(funs(sum)) ## dplyr syntax DT[, (cols) := lapply(.SD, sum), by = z] ans <- DF %>% group_by(z) %>% mutate_each(funs(sum)) # case (b) DT[, c(lapply(.SD, sum), lapply(.SD, mean)), by = z] DF %>% group_by(z) %>% summarise_each(funs(sum, mean)) # case (c) DT[, c(.N, lapply(.SD, sum)), by = z] DF %>% group_by(z) %>% summarise_each(funs(n(), mean))
-
(a)の場合、コードはほぼ等価である。
lapply()
一方dplyr
が導入されます。*_each()
への関数の束と一緒にfuns()
. -
data.tableの
:=
は列名を提供する必要がありますが、dplyrはそれを自動的に生成します。 -
(b)の場合、dplyrの構文は比較的わかりやすい。複数関数での集計・更新の改善はdata.tableのリストにある。
-
しかし、(c)の場合、dplyrは以下を返すでしょう。
n()
は一度だけでなく、カラムの数だけ繰り返されます。data.tableでは、リストを返すだけでよいのです。j
. リストの各要素は結果のカラムになります。そこで、もう一度、おなじみの基本関数であるc()
を連結して.N
をlist
を返します。list
.
注:もう一度言いますが、data.tableでは、リストを返すだけでよいのです。
j
. リストの各要素は、resultのカラムになります。あなたはc()
,as.list()
,lapply()
,list()
などの基本関数を使えば、新しい関数を覚えることなく、このようなことが実現できます。特殊な変数だけを覚える必要があります -。
.N
と.SD
は少なくとも dplyrでの同等品はn()
と.
-
-
接合部
dplyrは結合の種類ごとに別々の関数を提供しますが、data.tableでは同じ構文で結合を行うことができます。
DT[i, j, by]
(そして理由もある)。また、同等のmerge.data.table()
という関数で代用できる。setkey(DT1, x, y) # 1. normal join DT1[DT2] ## data.table syntax left_join(DT2, DT1) ## dplyr syntax # 2. select columns while join DT1[DT2, .(z, i.mul)] left_join(select(DT2, x, y, mul), select(DT1, x, y, z)) # 3. aggregate while join DT1[DT2, .(sum(z) * i.mul), by = .EACHI] DF1 %>% group_by(x, y) %>% summarise(z = sum(z)) %>% inner_join(DF2) %>% mutate(z = z*mul) %>% select(-mul) # 4. update while join DT1[DT2, z := cumsum(z) * i.mul, by = .EACHI] ?? # 5. rolling join DT1[DT2, roll = -Inf] ?? # 6. other arguments to control output DT1[DT2, mult = "first"] ??
-
それぞれの結合(left, right, inner, anti, semiなど)に対して別々の関数を使う方が良いと思う人もいるかもしれませんし、data.tableの
DT[i, j, by]
またはmerge()
であり、ベースRと同様である。 -
しかし、dplyrのjoinはそれだけを行います。それ以上ではありません。それ以下でもありません。
-
data.tablesは結合中に列を選択できる(2)、dplyrの場合は
select()
上記のように結合する前に、まず両方のdata.frameで結合を行います。そうしないと、不要な列を後で削除するために結合を複雑にすることになり、非効率です。 -
data.tablesは 結合時のアグリゲート を使って
by = .EACHI
機能(3)と、さらに 参加中更新 (4). わずかなカラムを追加/更新するために、なぜ結合結果全体を実体化するのですか? -
data.tableは、以下の機能を備えています。 ローリングジョイン (5) - ロール 前方、LOCF , ロールバック、NOCB , 最寄 .
-
data.tableはまた
mult =
を選択する引数です。 最初 , 最後 または すべて が一致する(6)。 -
data.tableには
allow.cartesian = TRUE
引数を使用することで、偶発的な無効結合から保護することができます。
もう一度言いますが、構文は
DT[i, j, by]
を追加し、さらに出力を制御することができます。
-
do()
...dplyrのsummariseは、単一の値を返す関数のために特別に設計されています。もし、関数が複数の値や不等な値を返す場合は、次のようにする必要があります。
do()
. すべての関数の戻り値について、あらかじめ知っておく必要があります。DT[, list(x[1], y[1]), by = z] ## data.table syntax DF %>% group_by(z) %>% summarise(x[1], y[1]) ## dplyr syntax DT[, list(x[1:2], y[1]), by = z] DF %>% group_by(z) %>% do(data.frame(.$x[1:2], .$y[1])) DT[, quantile(x, 0.25), by = z] DF %>% group_by(z) %>% summarise(quantile(x, 0.25)) DT[, quantile(x, c(0.25, 0.75)), by = z] DF %>% group_by(z) %>% do(data.frame(quantile(.$x, c(0.25, 0.75)))) DT[, as.list(summary(x)), by = z] DF %>% group_by(z) %>% do(data.frame(as.list(summary(.$x))))
-
.SD
に相当するのは.
-
data.tableでは、かなり多くのものを投げることができます。
j
- 唯一覚えておくべきことは、リストの各要素がカラムに変換されるように、リストを返すということです。 -
dplyrでは、それができません。そのため
do()
関数が常に単一の値を返すかどうか、どの程度確信が持てるかによりますが。そして、それはかなり遅いです。
もう一度言いますが、data.tableの構文は、以下のように一貫しています。
DT[i, j, by]
. で式を投げ続ければいいのです。
j
このようなことを気にする必要はありません。
をご覧ください。 このSOの質問 と これ . dplyrの構文を使って、答えをストレートに表現できないかなぁ...。
<ブロッククオート要約すると、特に強調したのは いくつか dplyrの構文が非効率的であったり、制限があったり、操作を単純化できなかったりする事例があります。これは特に、data.tableが(上記の貼り付けやリンクのような)読みにくく、学びにくい構文についてかなりの反発を受けるからです。dplyrを取り上げたほとんどの記事は、最も簡単な操作について話しています。そして、それは素晴らしいことです。しかし、その構文と機能の制限を認識することも重要であり、私はまだそれについての記事を見たことがありません。
data.tableにも癖があります(そのうちのいくつかは私が指摘し、私たちが修正しようとしているものです)。また、data.tableのjoinを改善しようとしているところです。 こちら .
<ブロッククオートしかし、dplyrがdata.tableと比較して欠けている機能の数も考慮する必要があります。
4. 特徴
これまで、ほとんどの機能を指摘してきました。 こちら と、この記事でも紹介しています。さらに
-
恐怖 - fast file readerは、以前から利用可能です。
-
fwrite - a 並列化された 高速ファイルライターが利用可能になりました。参照 この記事 は、実装の詳細な説明と #1664 は、今後の開発状況を追跡するために使用されます。
-
自動インデックス作成 - も、Rの基本構文をそのまま内部で最適化するための便利な機能です。
-
アドホックなグループ化 :
dplyr
の間に変数をグループ化し、結果を自動的にソートします。summarise()
これは常に望ましいとは限りません。 -
上記のdata.table結合における多くの利点(速度、メモリ効率、構文)。
-
非等式結合 : 他の演算子による結合を許可する
<=, <, >, >=
と、data.tableの結合の他のすべての利点を併せ持つ。 -
オーバーラップレンジジョイン が最近 data.table で実装されました。チェック 本論文 は、ベンチマークを含む概要をご覧ください。
-
setorder()
関数で、data.table の参照による並べ替えを高速に行うことができます。 -
dplyrは以下を提供します。 データベースへのインターフェイス は同じ構文を使っていますが、data.table は今のところそうではありません。
-
data.table
は、より高速な同等品を提供します。 りったいしゅうごうえんざん (ヤン・ゴレッキ作)・・・。fsetdiff
,fintersect
,funion
とfsetequal
加えてall
引数で指定します(SQL と同様)。 -
data.tableは、マスキングの警告を出さずにきれいにロードされ、以下のようなメカニズムを持っています。 こちら について
[.data.frame
R パッケージに渡されたときの互換性 dplyr は基本関数filter
,lag
と[
を使用すると、問題を引き起こす可能性があります; 例えば ここで と こちら .
最後に
-
データベースについて - data.tableが同様のインターフェイスを提供できない理由はありませんが、これは今のところ優先事項ではありません。しかし、これは今は優先順位が低いです。もしユーザーがその機能を強く望めば、優先順位が上がるかもしれません。
-
並列化について - 何事も、誰かが実行に移すまでは難しいものです。もちろん、努力は必要です(スレッドセーフであること)。
-
現在(v1.9.7 devel)、既知の時間のかかる部分を並列化することで、少しずつ性能を向上させることが進められています。
OpenMP
.
-
現在(v1.9.7 devel)、既知の時間のかかる部分を並列化することで、少しずつ性能を向上させることが進められています。
関連
-
[解決済み】RでのMLEエラー:'vmmin'の初期値が有限でない
-
[解決済み】R ggplot2 で scale_x_discrete を使用する。
-
[解決済み】rbind(deparse.level, ...)でエラー:引数の列の数がRにマッチしていない
-
[解決済み】Rで文字ベクトルから引用符を削除する
-
[解決済み] na.fail.defaultのエラー:オブジェクトの値が見つからない - しかし、値が見つからないことはありません。
-
[解決済み】.External.graphics Rでエラーが発生しました。
-
[解決済み】dplyr: "Error in n(): 関数は直接呼ばれるべきではありません"
-
[解決済み】Rで相対的な頻度をプロットするためにhistをどのように使用しますか?
-
[解決済み】seq_alongはうまくいくが、seqが意図しない結果を生む例とは?
-
[解決済み] data.tablesのX[Y]結合では、なぜ完全な外部結合や左結合ができないのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】"置換する項目数が置換長の倍数でない "と表示されるのはなぜですか?
-
[解決済み】R - if文の引数の長さが0である。
-
[解決済み】RでKNN。trainとclassは長さが違う」?
-
[解決済み】rbind(deparse.level, ...)でエラー:引数の列の数がRにマッチしていない
-
[解決済み】二項演算子への非数値引数【非公開
-
[解決済み】 eval(expr, envir, enclos) でのエラー : オブジェクトが見つかりません。
-
[解決済み】行列式で「数値/複雑な行列/ベクトルの引数を必要とする」というエラーが発生する?
-
[解決済み】起動時にパーをデフォルト値にリセットする方法
-
[解決済み] .EACHIをdata.tableに入れるか?
-
[解決済み] 大規模なdata.tableのNAを置換する最速の方法