2016-06-28 7 views
2

のために参照によりサブセットと割り当てがRのdata.table:ループ

正規表現とデータテーブルの名前のベクトルを考えるには、以下のように...よく...簡単なもののように思えるが、:

library(data.table) 
regexes <- c(a="^A$") 
dt <- fread(" 
a,A,1 
a,B,1 
b,A,1 
") 

入力データテーブルが

dt 
# V1 V2 V3 
# 1: a A 1 
# 2: a B 1 
# 3: b A 1 

あるregexesにおける第一の要素のための私の目標は、次のようになります。

V1=="a"セットV3:=2V2が対応する正規表現^A$と一致する場合を除き、V3:=3

aは、私はまた、より多くの名前とオーバーループに正規表現を得た。^A$regexes[1]23はデモの目的のためだけであるである、names(regexes)[1]であり、データセットは、およそ300.000行です。)だから、

V1aV2(01

# V1 V2 V3 
# 1: a A 3 (*) 
# 2: a B 2 (**) 
# 3: b A 1 

(*)3ため期待出力であります)はV1aV2Bであるため)、
(**)2を正規表現に一致する^A$と一致していません。

私はこのようなサブセット化による正規表現とパイプをループにを試してみました:grepl、期待どおりに動作しません...

for (x in seq(regexes)) 
    dt[V1==names(regexes)[x], V3:=2][grepl(regexes[x], V2), V3:=3] 

しかし...

dt 
# V1 V2 V3 
# 1: a A 3 
# 2: a B 2 
# 3: b A 3 <- wrong, should remain 2 

V1=="a"サブセットだけでなく、完全なV2列を使用します。私もうまくいきましたが、時間がかかりました(つまり、data.tableを使用する方法ではありません)。

質問:ここに行く最良のデータテーブルの方法は?私はpackageVersion("data.table")‘1.9.7’を使用しています。


私はデータフレームの経路に行くことができることに注意してください。もちろん - - この

df <- as.data.frame(dt) 
for (x in seq(regexes)) { 
    idx <- df$V1==names(regexes)[x] 
    df$V3[idx] <- 2 
    df$V3[idx][grepl(regexes[x], df$V2[idx])] <- 3 # or ifelse() 
} 

しかしように私は、可能な場合data.tableに戻し、その後data.frameにdata.tableを変換したくないでしょう。

ありがとうございます!予想通り

+0

'dt [condition、blah:= boo]'は修正*完全* 'dt'を返します。最後に空の' [] 'を追加することで確認できます。追加の条件を '[]'の2番目のセットに追加してください。 – eddi

+0

私はそれを試しました、しかし、 '' V1 == names(regexes)[x]とgrepl(regexes [x]、V2) 'を条件として使うと(すなわち、すべての' V2'に対して各正規表現にマッチさせます) 〜35秒かかりますが、データフレームの例は〜3です。だから私はそれが明らかにここに行く方法ではないと思った。 – lukeA

+0

何か怪しいようです。減速が見られる大きな例を追加できますか? – eddi

答えて

3

...それはgreplが完了V2列だけでなく、V1=="a"サブセットを使用して、動作しません。

library(stringi) 
dt[V1 %in% names(regexes), 
    V3 := V3 + 1L + stri_detect(V2, regex = regexes[V1]) 
] 

    V1 V2 V3 
1: a A 3 
2: a B 2 
3: b A 1 

機能のstri_detect家族がベースからgreplのようなものです:

私は正規表現のテストを簡単にベクトル化することができますstringiを使用します。

+0

フランクに感謝、 'stri_detect'についてまだ知りませんでした。しかし、 '名前(正規表現)'と '正規表現'は私の実際のデータに結びついていて、 'regexes'は実際は数値ではありません(私は誤解を招く恐れがありました。私はまだそれを克服する最良の方法は、(1)各 '名前(正規表現)'をサブセット化すること、(2)デフォルト値を設定すること、(3)マッチに新しい値を設定することだと思う。もっと良い例を見つけなければならないかどうか教えてください... – lukeA

+0

@lukeA私は従いません。この方法は正規表現が数値であるとは想定していません...もしあなたの例のサイズがこのように遅くなるようなものがあれば、それは良い例です( 'n'の関数として) ) 良いでしょう。 – Frank

+0

私は、ターゲット列である「V3」が数値でないことを意味します。私は(1)サブセット(=名前(正規表現))のデフォルト値に設定し、次に(2)そのサブセットの正規表現マッチのフラグ値に設定すると考えました。ここで重要なことは、各サブセットには独自の正規表現があることです。したがって、正規表現をベクトル化することはできません。 – lukeA