2016-11-06 7 views
0

興味のある要素の少なくとも1つを含むグループをすべて選択したいのですが、中間配列を作成することでこれを行うことができましたが、何かがより簡単で速くなる。私の実際のデータセットは1M行(および20列)を超えているため、中間配列を作成するのに十分なメモリがあるかどうかはわかりません。もっと重要なのは、私の元のファイルの以下のメソッドには多くの時間がかかります。少なくとも1つの一致条件を持つグループ化された行を選択

ここに私のコードとデータです:

a)のデータ

dput(Data_File) 
structure(list(Group_ID = c(123, 123, 123, 123, 234, 345, 444, 
444), Product_Name = c("ABCD", "EFGH", "XYZ1", "Z123", "ABCD", 
"EFGH", "ABCD", "ABCD"), Qty = c(2, 3, 4, 5, 6, 7, 8, 9)), .Names = c("Group_ID", 
"Product_Name", "Qty"), row.names = c(NA, 8L), class = "data.frame") 

b)のコード:私は、少なくとも1 Product_Name = ABCD

#Find out transactions 
    Data_T <- Data_File %>% 
     group_by(Group_ID) %>% 
     dplyr::filter(Product_Name == "ABCD") %>% 
     select(Group_ID) %>% 
     distinct() 

    #Now filter them 
    Filtered_T <- Data_File %>% 
     group_by(Group_ID) %>% 
     dplyr::filter(Group_ID %in% Data_T$Group_ID) 

C)の予想される出力を持っているGroup_IDを選択したいですis

Group_ID Product_Name Qty 
    <dbl>  <chr> <dbl> 
     123   ABCD  2 
     123   EFGH  3 
     123   XYZ1  4 
     123   Z123  5 
     234   ABCD  6 
     444   ABCD  8 
     444   ABCD  9 

私はこれで3時間以上苦労しています。私はSO:Select rows with at least two conditions from all conditionsによって自動提案されたスレッドを見ましたが、私の質問は非常に異なります。

答えて

3

私はこのようにそれを行うだろう:

Data_File %>% group_by(Group_ID) %>% 
    filter(any(Product_Name %in% "ABCD")) 
# Source: local data frame [7 x 3] 
# Groups: Group_ID [3] 
# 
# Group_ID Product_Name Qty 
#  <dbl>  <chr> <dbl> 
# 1  123   ABCD  2 
# 2  123   EFGH  3 
# 3  123   XYZ1  4 
# 4  123   Z123  5 
# 5  234   ABCD  6 
# 6  444   ABCD  8 
# 7  444   ABCD  9 

説明:条件に一致する(グループ内の)任意の行がある場合any()TRUEを返します。長さ1の結果は、グループの全長にリサイクルされ、グループ全体が保持されます。あなたは条件としてsum(Product_name %in% "ABCD") > 0でそれを行うこともできますが、anyはとてもうまく読みます。 3つ以上の一致する製品名のような、より複雑な条件を使用する場合は、代わりにsumを使用してください。

NAで動作がよく、複数の製品をグループ単位で確認したい場合は、展開しやすいので、%in%==を好きです。


速度と効率が問題になる場合は、data.tableが高速になります。私はフィルタリングのためのキー結合に依存し、非data.table操作を使用しないので、非常に高速でなければなりません:

library(data.table) 
df = as.data.table(df) 
setkey(df) 
groups = unique(subset(df, Product_Name %in% "ABCD", Group_ID)) 
df[groups, nomatch = 0] 
# Group_ID Product_Name Qty 
# 1:  123   ABCD 2 
# 2:  123   EFGH 3 
# 3:  123   XYZ1 4 
# 4:  123   Z123 5 
# 5:  234   ABCD 6 
# 6:  444   ABCD 8 
# 7:  444   ABCD 9 
+0

まずはお手数ですが、どうもありがとうございます。これはうまくいきますが、私がdata.tableを使ってこれを行うことができるかどうか知っていますか?私は初心者ですが、私はdata.tableが一般的にdplyrよりも速いことを読んでいます。そうですか?もしそうなら、私はあなたの助けに感謝します。私はメモリ効率とスピードも求めているので、これを頼んでいます。私の状況を理解してくれることを願っています – watchtower

+1

@watchtower:これが動作するかどうかを確認してください: dt = data.table(Data_File); dt [、x1:= ifelse(any(% "ABCD"のProduct_Name%)、T、F)、by = c( "Group_ID")];サブセット(dt、dt $ x1)[、1:3、with = F] –

+0

ありがとうJoel!これはうまくいく!完璧。 – watchtower

関連する問題