2016-11-02 6 views
3

私はRが新です。ループ内のサブセットを作成するより速い方法または適用関数R

データフレーム内を行単位で移動し、その行内の他の列や全く異なるデータフレームを参照するロジックに基づいて値を変更する最適な方法を見つけようとしています。問題は、私が使用しているロジックでは、最小値を取得するために各行のデータフレームを作成してサブセット化する必要があるということです。私の実際のデータセットは47000行と15列なので、47000個のサブセットの作成には長い時間がかかります。

私が話していることを説明するのに役立つサンプルデータセットです。

df1 <- data.frame('A' = c(rep("Beer", 2), rep("Chip", 2)), 'B' = c(NA, 3, 
     NA,9), 'C' = 5:8, 'D' = NA) 
df2 <- data.frame('Q' = c(rep("Beer", 2), rep("Chip", 2)), 'R' = 6:9, 'S' = 
     c(12, 15, 4, 18), 'T' = c(23, 45, 75, 34)) 

DF1:

A B C D 
Beer NA 5 NA 
Beer 3 6 NA 
Chip NA 7 NA 
Chip 9 8 NA 

DF2:

Q R S T 
Beer 6 12 23 
Beer 7 15 45 
Chip 8 4  75 
Chip 9 18 34 

このループは、すなわちそれがない場合、値は、NA列Bであるか否かをチェックし、私が何をしたいんその値がNAの場合は列Dに対してその値を使用し、その後、df2のフィルター処理されたサブセットから最小値を取得します。実際の使用例では、私は他のフィルタリング条件を持っています。

require(dplyr) 

for (i in 1:nrow(df1)) { 
    if (!(is.na(df1$B[i]))) { 
    df1$D[i] <- df1$B[i]} 
    else {x <- filter(df2, df1$A[i] == df2$Q) 
     x <- min(x$S) 
     df1$D[i] <- x 
    } 
} 

(もう少し従うことは困難であるが)誰もがRでループを避けるために言うので、私はまた働く適用使用してこの機能を作成しました:

FUNC <- function(x) { 
    apply(x, 1, function(y) { 
    if (!(is.na(y[2]))) { 
     y[4] <- y[2]} 
    else {z <- filter(df2, y[1] == df2$Q) 
    z <- min(z$S) 
    y[4] <- z} 
    } 
) 
} 

df1$D <- as.numeric(FUNC(df1)) 

出力:

 A B C D 
    Beer NA 5 12 
    Beer 3 6 3 
    Chip NA 7 4 
    Chip 9 8 9 

その他の質問:ベクトルyのアイテムをインデックス位置ではなく名前で参照する方法はありますか?

これを行うには良い方法がありますか?現在のところ、どちらの方法も47,000+行を実行するには約5-8分かかります。

+0

はい、これを改善できるはずです... 2つの異なるデータフレームで物事を少しでも妨害する可能性があります。これにはどんな理由がありますか? – roman

+0

これは、sqldfを使用してデータベース結合を行うより大きなプロセスにおける中間的なステップです。プロセスの初期段階でこの価値をもたらすより良い方法があるかもしれませんが、私はこれについてどうやって行くのか分かりません。 – FishShalami

答えて

0
df1$D <- df2 %>% 
    rename(A=Q) %>% 
    group_by(A) %>% 
    summarise(D=min(S)) %>% 
    right_join(df1, by="A") %>% 
    mutate(D=ifelse(is.na(B), D.x, B)) %>% 
    `[[`("D") 
関連する問題