2016-12-22 7 views
1

Rプログラミングでは比較的新しいので、カスタム関数を使用してdplyrを使用してデータフレームの新しい列を評価する方法を理解しようとしています。 data.tableを効率よくメモリに格納します。誰かがdplyr/data.tableを使用してデータフレームにカスタム関数を使用して新しい列を追加する

をここで助けてください私の問題の概要です

データは、1と2をフレームこれらのデータフレームは、数百万レコードを持つ列

df1 <- data.frame(col1 = c("A", "B", "C"), col2 = c(10,20,30)) 
df2 <- data.frame(col1 = c("DA", "EE", "FB", "C"), col2 = c(10,20,30,40)) 

の同じ種類と数を持っています。

ここで、df2の値を使用してデータフレームの1つ(たとえばdf1)に新しい列を追加します。

library(dplyr) 

calculateCol3 <- function(word) { 
df2 %>% 
    filter(grepl(paste0(word, "$"),col1))%>% 
    summarize(col3= sum(col2)) 
col3 
} 

df1 %>% group_by(col1) %>% mutate(col3 = calcualteCol3(col1)) 

このメソッドは動作しますが、それは痛々しいほど遅いですし、私はこれが原因でデータをコピーするのだと思いますが、あまりにも多くの時間を設定します。誰かが同じことをするより良い方法を提案することができますか?期待される結果は次のとおりです。

col1 col2 col3 
    A 10 10 
    B 20 30 
    C 30 40 

dt1 <- data.table(df1) 
dt2 <- data.table(df2) 

dt1[, col3 := calculateCol3(col1)}, by = 1:nrow(dt1)] 

を次のように私もdata.tableにデータフレームを変換しようとしたすべてが遅くなるようです。これを達成するためのより良い方法があると確信しています。誰かがfuzzyjoinパッケージを使用

おかげ

+0

はうん、原則として、あなたの関数を記述してみてください、あなたの所望の機能を, by = .EACHIを追加し、指定しているので別々にNROWを適用する必要はありません。 (あなたの関数が何をすべきか分かりませんので、より具体的な何かを手助けすることはできません) – Frank

+2

あなたのサンプルコードはまったく動作しません。 – thelatemail

+0

'df3 = grepl(paste0(word、 '$')、df2 $ col1))'は 'TRUE/FALSE'バイナリでなければなりません。 'df3 $ col2'はどのように動作すると思いますか? – Aramis7d

答えて

0

を助けることができる、私はあなたがこの作品を作ることができると思います。たとえば、

#install.packages("fuzzyjoin") 
df1$col1regex <- paste0(df1$col1,"$") 
regex_join(df2, df1, by=c(col1="col1regex"), mode="right") 

# col1.x col2.x col1.y col2.y col1regex 
#1  DA  10  A  10  A$ 
#2  FB  30  B  20  B$ 
#3  C  40  C  30  C$ 
3

効率的なソリューションが必要な場合は、正規表現を使用しないで行単位の操作を行わないことをおすすめします。あなたの関数がやっているすべては最後の文字で参加する場合は、あなただけの正規表現を使用せずに、それは後者を得ることができ、その後、バイナリは、あなたの関数を見ることで、今(効率のために)

library(data.table) 
setDT(df2)[, EndWith := substring(col1, nchar(as.character(col1)))] 
setDT(df1)[df2, col3 := i.col2, on = .(col1 = EndWith)] 
df1 
# col1 col2 col3 
# 1: A 10 10 
# 2: B 20 30 
# 3: C 30 40 

data.tableを使用して参加します1回の結合につきdf2$col2の値を合計しようとしているようです。問題はありません。data.tableでもバイナリジョインをしながら関数を実行できます。これはあなたのdf2(あなたが最後の文字ごとに単一の値以上のものを持っているときだけで説明するために)

df2 <- data.frame(col1 = c("DA", "FA", "EE", "FB", "C", "fC"), col2 = c(10,20,10,30,40,30)) 
df2 
# col1 col2 
# 1 DA 10 
# 2 FA 20 
# 3 EE 10 
# 4 FB 30 
# 5 C 40 
# 6 fC 30 

第2のステップは、バイナリを伴いますが最初のステップは、同じ

setDT(df2)[, EndWith := substring(col1, nchar(as.character(col1)))] 

であると言うことができますjoin-はちょうど反対の方法に、

setDT(df2)[df1, .(col2 = i.col2, col3 = sum(col2)), on = .(EndWith = col1), by = .EACHI] 
# EndWith col2 col3 
# 1:  A 10 30 
# 2:  B 20 30 
# 3:  C 30 70 
+1

ありがとうございました。その解決策は本当に速いです。 – user7328626

+0

@David Arenburgその質問は重複していたので、私はあなたの答えが好きでした!あなたロック – nik

関連する問題