2016-09-18 4 views
4

私は顧客のデータフレームpuzzleと彼らが所有するアイテムのタイプを持っています。顧客が複数のアイテムを持っている場合、顧客はリスト上で複数回出現することができます。各ペアの人数の割合を取得

name type 
m1  A 
m10  A 
m2  A 
m9  A 
m9  B 
m4  B 
m5  B 
m1  C 
m2  C 
m3  C 
m4  C 
m5  C 
m6  C 
m7  C 
m8  C 
m1  D 
m5  D 

「A」を所有し、「B」を所有している人の割合を計算したいと思います。上記の入力に基づいて

、私はこの使用してRのような出力を得ることができる方法:あなたの助けを

A  B  C  D  TOTAL 
A 1  0.25 0.5 0.25 4 
B 0.33 1  0.67 0.33 3 
C 0.25 0.25 1  0.25 8 
D 0.5 0.5 1  1  2 

おかげでたくさん!


ここでそれを行うには長いとマニュアルの方法は一切ループや高度な機能(ただし、Rで潜在能力を無駄にされて当然の)で、次のとおりです。項目Aのための

例: -

所有
puzzleA <- subset(puzzle, type == 'A') 

計算、顧客、誰も自分のB: -

length(unique((merge(puzzleA, puzzleB, by = 'name'))$name))/length(unique(puzzleA$name) 

:私の質問と回答の

データ

puzzle <- structure(list(name = c("m1", "m10", "m2", "m9", "m9", "m4", 
      "m5", "m1", "m2", "m3", "m4", "m5", "m6", "m7", "m8", "m1", "m5" 
     ), type = c("A", "A", "A", "A", "B", "B", "B", "C", "C", "C", 
      "C", "C", "C", "C", "C", "D", "D")), .Names = c("name", "type" 
     ), class = "data.frame", row.names = c(NA, -17L)) 

答えて

2

ちょうど良いアプリケーション。

## separate out people by type 
lst <- with(puzzle, split(name, type)) 

#List of 4 
# $ A: chr [1:4] "m1" "m10" "m2" "m9" 
# $ B: chr [1:3] "m9" "m4" "m5" 
# $ C: chr [1:8] "m1" "m2" "m3" "m4" ... 
# $ D: chr [1:2] "m1" "m5" 

## pairwise intersect (a matrix of list) 
pair_intersect <- outer(lst, lst, Vectorize(intersect)) 

# A   B   C   D   
#A Character,4 "m9"  Character,2 "m1"  
#B "m9"  Character,3 Character,2 "m5"  
#C Character,2 Character,2 Character,8 Character,2 
#D "m1"  "m5"  Character,2 Character,2 

## count number of people in each pair 
count <- matrix(lengths(pair_intersect), nrow = length(lst), 
       dimnames = dimnames(pair_intersect)) 

# A B C D 
#A 4 1 2 1 
#B 1 3 2 1 
#C 2 2 8 2 
#D 1 1 2 2 

## conditional percentage 
conditional_percent <- count/diag(count) 

#   A B   C   D 
#A 1.0000000 0.25 0.5000000 0.2500000 
#B 0.3333333 1.00 0.6666667 0.3333333 
#C 0.2500000 0.25 1.0000000 0.2500000 
#D 0.5000000 0.50 1.0000000 1.0000000 

あなたはまた、例えば、アソシエーションルールのセットを構築することができ

final <- cbind(conditional_percent, Total = diag(count)) 

#   A B   C   D Total 
#A 1.0000000 0.25 0.5000000 0.2500000  4 
#B 0.3333333 1.00 0.6666667 0.3333333  3 
#C 0.2500000 0.25 1.0000000 0.2500000  8 
#D 0.5000000 0.50 1.0000000 1.0000000  2 
3

を使用し、最後の列に対角線を追加したいはずです。

library(arules) 
trans <- as(lapply(split(puzzle[2], puzzle[1]), unlist, F, F), "transactions") 
rules <- apriori(trans, parameter = list(support=0, minlen=2, maxlen=2, conf=0)) 
res <- data.frame(
    lhs = labels(lhs(rules)), 
    rhs = labels(rhs(rules)), 
    value = round([email protected]$confidence, 2) 
) 
res <- reshape2::dcast(res, lhs~rhs, fill = 1) 
res$total <- rowSums([email protected]) 
res 
# lhs {A} {B} {C} {D} total 
# 1 {A} 1.00 0.25 0.50 0.25  4 
# 2 {B} 0.33 1.00 0.67 0.33  3 
# 3 {C} 0.25 0.25 1.00 0.25  8 
# 4 {D} 0.50 0.50 1.00 1.00  2 
3

我々はこれを行うことができますmerge/tableである。 mergeデータセット自体がbyの '名前'で、最初の列を削除し、table( 'tbl')の頻度カウントを取得し、 'tbl'の対角要素で除算し、対角要素でcbindを除算します。

tbl <- table(merge(puzzle, puzzle, by = "name")[-1]) 
cbind(round(tbl/diag(tbl),2), TOTAL= diag(tbl)) 
#  A B C D TOTAL 
#A 1.00 0.25 0.50 0.25  4 
#B 0.33 1.00 0.67 0.33  3 
#C 0.25 0.25 1.00 0.25  8 
#D 0.50 0.50 1.00 1.00  2 
3

Akrunの回答と同様に、データをテーブル化し、クロスプロダクトを利用して共通の値を見つけることができます。比率は対角線で割ることによって計算されます。

tab <- crossprod(table(puzzle)) 
cbind(tab/diag(tab), total=diag(tab)) 

#   A B   C   D total 
# A 1.0000000 0.25 0.5000000 0.2500000  4 
# B 0.3333333 1.00 0.6666667 0.3333333  3 
# C 0.2500000 0.25 1.0000000 0.2500000  8 
# D 0.5000000 0.50 1.0000000 1.0000000  2 
関連する問題