1

投稿の下部にある「地図」または「注文」の明確化

いくつかの論理列を持つデータ フレームと、それらの論理列の特定の組み合わせに対して値を与える「マップ」があるとします。

データフレームの各行に関連付けられた値を計算するための最良/最も効率的な方法は何ですか?

以下に、ifelse()、merge()、および table() の 3 つの解決策があります。コメントや代替ソリューションをいただければ幸いです。

【長文失礼します】

次のデータ フレームの例を考えてみましょう。

# Generate example
#N <- 15
#Data <- data.frame(A=sample(c(FALSE,TRUE),N,TRUE,c(8,2)),
#               B=sample(c(FALSE,TRUE),N,TRUE,c(6,4)),
#               C=sample(c(FALSE,TRUE),N,TRUE,c(7,3)),
#               D=sample(c(FALSE,TRUE),N,TRUE,c(7,3)))

# Specific example used in this question
Data <- structure(list(A = c(FALSE, FALSE, FALSE, TRUE, FALSE, FALSE,
  FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE),
  B = c(FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE,
  FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE), C = c(FALSE,
  FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE,
  FALSE, TRUE, FALSE, FALSE, FALSE), D = c(TRUE, FALSE, FALSE,
  FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE,
  FALSE, TRUE, FALSE)), .Names = c("A", "B", "C", "D"), 
  class = "data.frame", row.names   = c(NA,-15L))


        A     B     C     D
 1  FALSE FALSE FALSE  TRUE
 2  FALSE FALSE FALSE FALSE
 3  FALSE  TRUE FALSE FALSE
 4   TRUE FALSE FALSE FALSE
 5  FALSE FALSE FALSE FALSE
 6  FALSE  TRUE FALSE FALSE
 7  FALSE  TRUE FALSE FALSE
 8  FALSE FALSE FALSE FALSE
 9  FALSE FALSE FALSE FALSE
 10  TRUE FALSE  TRUE  TRUE
 11 FALSE  TRUE FALSE  TRUE
 12 FALSE FALSE  TRUE FALSE
 13 FALSE  TRUE FALSE FALSE
 14 FALSE FALSE FALSE  TRUE
 15 FALSE FALSE FALSE FALSE

次のマップと組み合わせます。

# A -> B -> C                                                                                                                                                                                                        
#   \_  D  

### To clarify, if someone has both B & D TRUE (with C FALSE), D is higher than B
### i.e. there can be no ties

これにより、論理列の順序が定義されます。私が望む最終的な値は、各行内の「最も高い」列です。そのため、列 C が true の場合、常に C を返します。C が FALSE で D が true の場合にのみ、"D" を返します。

これを行う単純な方法は、ネストされた ifelse ステートメントです。

Data$Highest <- with(Data, ifelse( C, "C",
                                  ifelse( D, "D",
                                         ifelse( B, "B",
                                                ifelse( A, "A", "none")
                                                )
                                         )
                                  )
                     )

しかし、そのコードは読み取り/保守が難しく、多くの列を持つ複雑な順序付けでは非常に複雑になります。

列の組み合わせから目的の出力へのマッピングをすばやく生成できます。

Map <- expand.grid( lapply( lapply( Data[c("A","B","C","D")], unique ), sort ) )

Map$Value <- factor(NA, levels=c("A","B","C","D","none"))
Map$Value[which(Map$A)] <- "A"
Map$Value[which(Map$B)] <- "B"
Map$Value[which(Map$D)] <- "D"
Map$Value[which(Map$C)] <- "C"
Map$Value[which(is.na(Map$Value))] <- "none"

        A     B     C     D Value
 1  FALSE FALSE FALSE FALSE  none
 2   TRUE FALSE FALSE FALSE     A
 3  FALSE  TRUE FALSE FALSE     B
 4   TRUE  TRUE FALSE FALSE     B
 5  FALSE FALSE  TRUE FALSE     C
 6   TRUE FALSE  TRUE FALSE     C
 7  FALSE  TRUE  TRUE FALSE     C
 8   TRUE  TRUE  TRUE FALSE     C
 9  FALSE FALSE FALSE  TRUE     D
 10  TRUE FALSE FALSE  TRUE     D
 11 FALSE  TRUE FALSE  TRUE     D
 12  TRUE  TRUE FALSE  TRUE     D
 13 FALSE FALSE  TRUE  TRUE     C
 14  TRUE FALSE  TRUE  TRUE     C
 15 FALSE  TRUE  TRUE  TRUE     C
 16  TRUE  TRUE  TRUE  TRUE     C

merge() で使用できるもの:

merge( Data, Map, by=c("A","B","C","D"), all.y=FALSE )

        A     B     C     D Highest Value
 1  FALSE FALSE FALSE FALSE    none  none
 2  FALSE FALSE FALSE FALSE    none  none
 3  FALSE FALSE FALSE FALSE    none  none
 4  FALSE FALSE FALSE FALSE    none  none
 5  FALSE FALSE FALSE FALSE    none  none
 6  FALSE FALSE FALSE  TRUE       D     D
 7  FALSE FALSE FALSE  TRUE       D     D
 8  FALSE FALSE  TRUE FALSE       C     C
 9  FALSE  TRUE FALSE FALSE       B     B
 10 FALSE  TRUE FALSE FALSE       B     B
 11 FALSE  TRUE FALSE FALSE       B     B
 12 FALSE  TRUE FALSE FALSE       B     B
 13 FALSE  TRUE FALSE  TRUE       D     D
 14  TRUE FALSE FALSE FALSE       A     A
 15  TRUE FALSE  TRUE  TRUE       C     C

ただし、現在、merge() 関数は行の順序を保持していません。ただし、これを回避する方法があります。

私の最終的なアイデアは、マップに対応する文字エントリを持つ 4 次元のテーブルを使用することでした。

Map2 <- table( lapply( Data[c("A","B","C","D")], unique ) )

Map2[] <- "none"
Map2["TRUE",,,] <- "A"
Map2[,"TRUE",,] <- "B"
Map2[,,,"TRUE"] <- "D"
Map2[,,"TRUE",] <- "C"

しかし、上記の行が不明確です (表を作成するためのより良い方法があるのではないでしょうか? Map を Map2 に変えることは可能だと思いましたが、方法がわかりませんでした)。

次に、matrix-indexing を使用して、対応する値を引き出します。

BOB <- as.matrix(Data[c("A","B","C","D")])
cBOB <- matrix(as.character(BOB),nrow=NROW(BOB),ncol=NCOL(BOB),dimnames=dimnames(BOB))

Data$Alt.Highest <- Map2[cBOB]


        A     B     C     D Highest Alt.Highest
 1  FALSE FALSE FALSE  TRUE       D           D
 2  FALSE FALSE FALSE FALSE    none        none
 3  FALSE  TRUE FALSE FALSE       B           B
 4   TRUE FALSE FALSE FALSE       A           A
 5  FALSE FALSE FALSE FALSE    none        none
 6  FALSE  TRUE FALSE FALSE       B           B
 7  FALSE  TRUE FALSE FALSE       B           B
 8  FALSE FALSE FALSE FALSE    none        none
 9  FALSE FALSE FALSE FALSE    none        none
 10  TRUE FALSE  TRUE  TRUE       C           C
 11 FALSE  TRUE FALSE  TRUE       D           D
 12 FALSE FALSE  TRUE FALSE       C           C
 13 FALSE  TRUE FALSE FALSE       B           B
 14 FALSE FALSE FALSE  TRUE       D           D
 15 FALSE FALSE FALSE FALSE    none        none

要約すると、この「マッピング」タイプの操作を実現するためのより良い方法と、これらの方法の効率に関する考えはありますか?

私が興味を持っているアプリケーションには、9 つ​​の列と、3000 行に適用する 3 つの枝を持つ順序付けチャートがあります。基本的に、扱いにくいデータ ストレージ形式に基づいて因子を構築しようとしています。そのため、コードの明快さは私の最優先事項であり、速度/メモリ効率は 2 番目です。

前もって感謝します。

PS 質問のタイトルを修正するための提案も歓迎します。

明確化

実際のアプリケーションには、回答者が所定の教育/資格レベルを達成しているかどうかを尋ねる 9 つの質問を含むアンケートが含まれます。これらは、バイナリの yes/no 応答です。

私たちが望むのは、「達成された最高の資格」という新しい変数を生成することです。

問題は、9 つ​​のレベルが単純なスタックを形成しないことです。たとえば、専門的な資格は大学に行かなくても取得できます (特に高齢の回答者)。

私たちは、応答のすべての組み合わせに対して「最高の資格」を持つように「マップ」または「順序付け」を設計しました (この順序は主観的なものであるため、代替順序の実装を簡単にするためです)。

# So given the nine responses: A, B, C, D, E, F, G, H, I
# we define an ordering as:
# D > C > B > A
# F > E
# E > A
# E == B
# I > H
# H == B
# G == B

# which has a set of order relationships. There is equality in this example

#    A -> B -> C -> D
#      \_ E -> F
#      \_ H -> I
#      \_ G

# 0  1    2    3    4     
# We could then have five levels in out final 'highest' ordered factor: none, 1, 2, 3, 4   

# Or we could decide to add more levels to break certain ties.

R の質問は、論理列の組み合わせを「最高達成」値にマップする順序 (および同点をどうするか) が与えられた場合です。これをRで実装する最善の方法.

4

2 に答える 2