2017-02-13 6 views
4

"オーバーラップ"変数に基づいて順次Group_IDを作成する方法を見つけることを試みています。私がこれを説明する最も簡単な方法は、住宅、ローン、および借り手の例を使用することです。Rの再帰的なグループ化

は、例えばハウス1(H_01)にリンクされているので 我々は

df <- data.frame(house  = c('H_01','H_02','H_03','H_04','H_05'), 
       loan  = c('L_01','L_02','L_02','L_03','L_04'), 
       borrower = c('B_01','B_01','B_02','B_03','B_04')) 

一つは、すべての変数(家、ローン、債務者)との間に多くの関係に多くを持っているだろうと仮定し、次の例があるとしローン1(L_01)と借り手1(B_01)。しかしB_01L_02にリンクされており、それ自体はH_02にリンクされていますが、H_03にもリンクされています。したがって、テーブルの最初の3行にはG_01(グループ1)というラベルを付ける必要があります。

H_04は、他のレコードに属していないL_03にリンクされており、どちらも4番目のレコードはG_02にする必要がありますのでB_03は、他のレコードに関連しています。そして、アナログ探査で、私たちはそのレコード5は、独自のサブグループにG_03

に属し見るべきエレガントdplyrを持ってする方法はあります(好ましくは、必ずしも必要ではないが)G_01G_02、およびG_03のこのグループ化を実現しますか?

+3

私の専門ではありませんが、networks/igraphのように聞こえます。 – alistaire

+0

この単純な例では、ベースRコード 'cumsum(pmin(c(1、diff(df $ loan))、c(1、diff(df $ borrower))))')がグループを計算します。しかし、初期の借り手が複数のローンを持っていて、複数の借り手とローンを共有している場合などは、一般的には機能しません。 – lmo

答えて

4

あなたは「接続されたコンポーネント」を探しています。最初にデータ(melt)を並べ替えて、関係をグラフとして扱い、よく実装されたグラフライブラリ(igraph)に作業を依頼することができます。あなたは、グラフを作成する前に、例えば、

with(melt(df,id="house"),data.frame(x=house,y=paste(variable,value,sep="."))) 

、一緒に「色」に値との関係のノードを貼り付けたいかもしれない一般化すること

library(reshape2) 
library(igraph) 

components(graph.data.frame(melt(df,id="house")[,c(1,3)]))$membership[df$house] 

    # H_01 H_02 H_03 H_04 H_05 
    # 1 1 1 2 3 

+0

ありがとう@ A.Webb - これは完全に動作し、非常にエレガントです。私はグラフデータベースにダイビングをしていませんでしたが、これは私が欠けているものの魅力的な例になりました。ボーナスとしてどの変数から_anchor_を開始するかが問題になります(あなたのコードでは 'House'で始まりますが、変数がn個ある場合は、私が選択した変数を変更しますか?) – Olivier

+0

重要ではありません最初のデフォルトグラフが向けられています。つまり、H_01からL_01までのエッジを指定し、その逆を指定したということです。 'directed = FALSE'を指定することもできますが、最初の行の関係は実際にはH_01〜L_01、H_01〜B_01、L_01〜B_01ですが、最初の2つの部分だけが含まれていますこの関係は接続性のように推移的であるため、これは重要ではありません。 –

1

A. Webbのソリューションは明らかに優れています。しかし、私がの解決策を見つけ出したので、ここに書きます。

df = data.frame(apply(df, 2, as.character), stringsAsFactors = FALSE) 
g = 1 
df$group[1] = paste("G",g,sep = "") 

#Find out unique groups and assign "CHECK" to rows in same groups 
for (i in 2:nrow(df)){ 
    if (any(df[i,1:3] %in% unlist(df[1:(i-1),1:3]))){ 
     df$group[i] = "CHECK" 
    } else { 
     g = g + 1 
     df$group[i] = paste("G",g,sep = "") 
    } 
} 

#Assign groups to rows in same group 
for (i in 1:nrow(df)){ 
    if (df$group[i] != "CHECK"){ 
     next 
    } 
    if (df$house[i] %in% df$house[1:i]){ 
     df$group[i] = df$group[match(df$house[i], df$house[1:i])]   
    } 
    if (df$loan[i] %in% df$loan[1:i]){ 
     df$group[i] = df$group[match(df$loan[i], df$loan[1:i])]   
    } 
    if (df$borrower[i] %in% df$borrower[1:i]){ 
     df$group[i] = df$group[match(df$borrower[i], df$borrower[1:i])]  
    } 
} 

#> df$group 
#[1] "G1" "G1" "G1" "G2" "G3" 
+1

@ d.bもおかげさまで、よく考えられた解決策ではありますが、_n_変数のために少し実装するのは難しいです。あなたの非常に迅速な返信をありがとう – Olivier