2017-02-28 4 views
-1

data.tableパッケージを使用してデータセットの一部を選択する関数を記述したいと思います。関数の宣言されたパラメータは、次のとおりdata.table:カスタム関数で条件付きのデータセットの一部を選択

  • 入力データセット(dset)、
  • データセットがサブセットであろうれる変数(seg.var)、変数(value)の上方宣言の
  • 値。

私は基本Rでの作業関数を記述することができました:

# Function without data.table 

data.select <- function(dset, seg.var, value){ 
    dset.out <- dset[dset[[seg.var]] == value,] 
    return(dset.out) 
} 

data.select(iris, "Species", "setosa") 

しかし、私はdata.tableパッケージでそれを書き換えることができません:以下の機能が動作しません。評価における

# Function with data.table 

data.select.dt <- function(dset, seg.var, value){ 
    dset <- as.data.table(dset) 
    dset.out <- dset[seg.var == value,] 
    return(dset.out) 
} 

data.select.dt(iris, Species, "setosa") 

エラー(exprは、ENVIR、enclos):がく片:5つのCOLSのオブジェクトの種 'が見つかりません

data.select.dt(iris, "Species", "setosa") 

空data.table(0行) .Length、Sepal.Width、Petal.Length、Petal.Width、Species

入力データセットはdata.frameフォーマットです。上記の関数を上書きするという目標は、パフォーマンスの向上です。どんな助けもありがとう。

+3

なぜ関数内でdata.tableに変換していますか?データセット全体のコピーを作成しています。 'setDT'を使って、すでに' data.table'を適切な場所に変換することで、すでに 'data.table'を操作する方が良いでしょう。いずれにせよ、私は単純なバイナリ結合を行います。 'data.select.dt

+0

残りのコードが確実に動作するようにしたいと思います。 'iris'より大きいデータセットを扱うので、コード全体を書き直すことなく、' data.table'で実装された 'base 'サブセットのパフォーマンスを比較したいと思います。 – kaksat

+0

@kaksat、私の答えで 'if(!data.table :: is.data.table(dset))'を見て、 'dset'が' data.table'なら時間とRAMを節約してください。 –

答えて

2

それはとても別々の答えは、コメントのためのビット長すぎる:

まず、R.S @にコメントとして私が言及したget()機能。答え:

data.select.dt.V1 <- function(dset, seg.var, value){ 
    if(!data.table::is.data.table(dset)) dset <- data.table::as.data.table(dset) # To convert only if needed 
    dset[get(seg.var) == value,] 
} 

data.select.dt.V1(iris, 'Species', 'setosa') 

そして、あなたは(data.table方法で、ウェル)表現として第二引数を渡すことができ、その後、さらにdata.table機能を、文字列ではありません:

data.select.dt.V2 <- function(dset, seg.var, value){ 
    if(!data.table::is.data.table(dset)) dset <- data.table::as.data.table(dset) # To convert only if needed 
    sv <- substitute(seg.var) 
    dset[eval(sv) == value,] 
} 

data.select.dt.V2(iris, Species, 'setosa') 

編集: @David Arenburgのコメントのおかげで、変換の簡素化とテストが機能します。

2編集:

data.select.dt.V3 <- function(dset, seg.var, value) data.table::as.data.table(dset)[.(value), on = seg.var] 

data.select.dt.V4 <- function(dset, seg.var, value) { 
    if(!data.table::is.data.table(dset)) dset <- data.table::as.data.table(dset) # To convert only if needed 
    dset[.(value), on = seg.var] 
} 

                expr  min  lq  mean median  uq  max neval cld 
1 res <- data.select.dt.V1(iris_df, "Species", "setosa") 3.804995 4.585763 4.150130 4.688093 5.320362 3.166503 10 c 
2 res <- data.select.dt.V2(iris_df, Species, "setosa") 3.713275 3.827180 3.865347 4.544968 4.753045 3.218075 10 c 
3 res <- data.select.dt.V3(iris_df, "Species", "setosa") 1.927947 1.942868 2.167127 2.328364 2.595420 2.159664 10 b 
4 res <- data.select.dt.V4(iris_df, "Species", "setosa") 1.987710 2.004497 2.011502 2.280117 2.856847 1.594249 10 b 

5 res <- data.select.dt.V1(iris_dt, "Species", "setosa") 2.771223 2.792428 2.501362 2.805796 3.056144 1.883520 10 b 
6 res <- data.select.dt.V2(iris_dt, Species, "setosa") 2.830161 2.970071 2.593192 3.123812 3.170884 1.752576 10 b 
7 res <- data.select.dt.V3(iris_dt, "Species", "setosa") 1.963530 2.116116 2.059718 2.203265 2.740949 1.768817 10 b 
8 res <- data.select.dt.V4(iris_dt, "Species", "setosa") 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 10 a 

が明確V4が1つである:は515メガバイトdata.tabledata.frameに@デビッドArenburgの(持つとis.data.tableチェックせずに、V3それぞれV4)一つと二つの機能上にベンチマークdata.framedata.tableの両方が期待される場合は、dfしか可能でない場合、最も速い関数はV3になります。

1

ここでは微妙なことがありますが、これを段階的に分解することをおすすめします。

あなたの元のコードは、関数の外で動作します:ストレート最初のコードを記述し、その関数に変換する...あなたはあるが失敗した機能でラップが

require(data.table) 

dset <- as.data.table(iris) 
dset.out <- dset[Species == "setosa",] 
dset.out 
> dset <- as.data.table(iris) 
> dset.out <- dset[Species == "setosa",] 
> dset.out 
Sepal.Length Sepal.Width Petal.Length Petal.Width Species 
1:   5.1   3.5   1.4   0.2 setosa 
2:   4.9   3.0   1.4   0.2 setosa 
... 

> require(data.table) 
> data.select.dt <- function(dset, seg.var, value){ 
+ dset <- as.data.table(dset) 
+ dset.out <- dset[ seg.var == eval(value) ] 
+ return(dset.out) 
+ } 
> data.select.dt(iris, Species, "setosa") 
Show Traceback 

Rerun with Debug 
Error in eval(expr, envir, enclos) : object 'Species' not found 

OK、興味深いですが、なぜ関数呼び出しで失敗するのですか? "Species"変数を正しく参照する必要があります。電話で参照解除が必要なもの:

dset[dset[["Species"]] == "setosa",] 
> dset[dset[["Species"]] == "setosa",] 
    Sepal.Length Sepal.Width Petal.Length Petal.Width Species 
1:   5.1   3.5   1.4   0.2 setosa 
2:   4.9   3.0   1.4   0.2 setosa 
... 

nb本当に興味深いのは、RStudioでデバッグを実行すると機能しますが、デバッグ以外のモードではエラーが発生するということです。

今、あなたは、機能でこれをラップすることができます:種は引用符"Species"に包まれていることを

data.select.dt <- function(dset, seg.var, value){ 
    dset <- as.data.table(dset) 
    dset.out <- dset[dset[[seg.var]] == value,] 
    return(dset.out) 
} 

注...

data.select.dt(iris, "Species", "setosa") 

data.select.dt(iris, "Species", "setosa") 
    Sepal.Length Sepal.Width Petal.Length Petal.Width Species 
1:   5.1   3.5   1.4   0.2 setosa 
2:   4.9   3.0   1.4   0.2 setosa 
3:   4.7   3.2   1.3   0.2 setosa 
+0

R.S.私の前で正解を与えた – Technophobe01

2

をあなたのコードをチェックしてください:dset.out <- dset[seg.var == value,]をdata.tableバージョンに最初に持っていたのはdset.out <- dset[dset[[seg.var]] == value,]である必要があります。

Speciesには、引用符がありません。この関数を呼び出すと、"Species"になります。そのため、ワークスペースにオブジェクトSpeciesがないというエラーメッセージが表示されます。

これは機能します。

data.select.dt <- function(dset, seg.var, value){ 
    dset <- as.data.table(dset) 
    dset.out <- dset[dset[[seg.var]] == value,] 
    return(dset.out) 
} 

data.select.dt(iris, "Species", "setosa") 

編集してヒントを追加すると、機能の外でデバッグするので、物事が壊れている場所がわかります。

+1

'dset [[seg.var] == value、]'を使うと、 'dset [[seg.var]]'を返していない)時間とメモリを節約することができます。 –