0

このようなデータ フレームがあるとします。これは、さまざまな回答者に対する調査の回答と考えることができます。

Data = 
ID Q1 Q2 Q3
1  A1 B2 C3
2  A2 B1 C2
3  A1 B2 C3
...

また、次のスコアテーブルもあります。

Q1 <- (c("A1", 10, "A2", 20, ...))
Q2 <- (c("B1", 10, "B2", 20, ...))
Q3 <- (c("C1", 10, "C2", 20, ...))

Q1で「A1」を選べば10点、Q2で「B2」を選べば20点以上、Q3で「C1」を選べば10点ということです。私が得た合計スコアは次のようになります: 10 (A1) + 20 (B2) + 10 (C1) = 40

次に、データのすべての行について、スコア テーブルに従って各列のスコアを合計して合計スコアを計算する必要があります。

簡単なコードを使用してそうする方法を教えてもらえますか? 今のところ、スコア テーブルを Xx2 行列にすることと、入れ子になった if と for ループをたくさん使うことしか考えられません。

4

3 に答える 3

1

データ:

Data <- read.table(text = "ID Q1 Q2 Q3
1  A1 B2 C3
2  A2 B1 C2
3  A1 B2 C3", header = TRUE)

Q1 <- c("A1", 10, "A2", 20)
Q2 <- c("B1", 10, "B2", 20)
Q3 <- c("C1", 10, "C2", 20)

最初に、Qオブジェクトのリストが作成されます。

Qlist <- list(Q1 = Q1, Q2 = Q2, Q3 = Q3)

今、sapply使用できます:

cbind(Data,
      QSum = rowSums(sapply(names(Qlist),
                            function(q)
                              as.numeric(Qlist[[q]][match(Data[[q]],
                                                          Qlist[[q]]) + 1])), 
                     na.rm = TRUE))

出力:

  ID Q1 Q2 Q3 QSum
1  1 A1 B2 C3   30
2  2 A2 B1 C2   50
3  3 A1 B2 C3   30
于 2012-11-23T10:52:54.007 に答える
1
df <- read.table(text="ID Q1 Q2 Q3
1  A1 B2 C3
2  A2 B1 C2
3  A1 B2 C3",header=TRUE, stringsAsFactors=FALSE)

scores <- list(
Q1 = c("A1", 10, "A2", 20, "A3", 30),
Q2 =c("B1", 30, "B2", 10, "B3", 20),
Q3 =c("C1", 10, "C2", 30, "C3", 20)
)

#lookup table
scores <- do.call("cbind",scores)

#match
m <- apply(df[,-1],2,match,table=scores)

#look up
points <- matrix(as.numeric(scores[m+1]),ncol=ncol(df)-1)

#sum for each ID
result <- cbind(df,Score=rowSums(points))

  ID Q1 Q2 Q3 Score
1  1 A1 B2 C3    40
2  2 A2 B1 C2    80
3  3 A1 B2 C3    40
于 2012-11-23T11:00:11.243 に答える
1

ローランドが選択した「スコア」を使用します。スコア テーブルを 2x2 マトリックスに変更できるとおっしゃっていたので、スコアのデータ構造が異なるという点で他の 2 つとは異なる以下のソリューションを提供します。

コードを提供する前に、ロジックを説明させてください。

  1. 行ごとに df を処理したい
  2. 行ごとに、質問ごとに選択された回答のスコアを使用したい
  3. まとめたいと思います

2に基づいて、質問番号と入力された回答に基づいて索引付けできる連想配列の必要性を感じています。したがって、スコアの次の表現を作成します。

> scores <- list(
+                 Q1 = list(A1=10,A2=20,A3=30),
+                 Q2 = list(B1=30,B2=10,B3=20),
+                 Q3 = list(C1=10,C2=30,C3=20)
+               )

基本的に、スコアはリストのリストになりました。これにより、次のことができます。

> scores[["Q1"]][["A1"]]
[1] 10

あとは、上記の「Q1」と「A1」をパラメータ化する方法を見つけるだけです。

データフレーム「df」は次のとおりです。

> df
  ID Q1 Q2 Q3
1  1 A1 B2 C3
2  2 A2 B1 C2
3  3 A1 B2 C3

私が気にしているのは、ID 列のない各行です。だから、私はそれを抽出します:

> df[1,-1]
  Q1 Q2 Q3
1 A1 B2 C3

ここまでで、最初のインデックスの列名をスコアに選択し、2 番目のインデックスの行の値を選択する必要があることがわかります。したがって、score[[column-M]][[row-NvalueForColumn-M]] を取得できれば、それらを合計できます。

列名は次のように簡単に取得できます。

> columnNames <- colnames(df[1,-1])
> columnNames
[1] "Q1" "Q2" "Q3"

したがって、必要なロジックを実行するための最後のコードは次のとおりです。

> columnNames <- colnames(df[1,-1])
> score <- c(0,0,0)
> for (i in 1:length(df[1,-1]))
+ {
+     for (j in 1:length(columnNames))
+     {
+         score[i] <- score[i] + scores[[columnNames[j]]][[df[i,-1][[columnNames[j]]]]]
+     }
+ }
> final <- cbind(df,score)
> final
  ID Q1 Q2 Q3 score
1  1 A1 B2 C3    40
2  2 A2 B1 C2    80
3  3 A1 B2 C3    40
> 

上記のコードは、(行合計などを使用して) 少なくとも 5 行削減できると思います。Sven のような経験豊富な人々は、上記のコードを気の利いた数行に改善できると確信しています。入力をいただければ幸いです。

于 2012-11-23T16:56:37.747 に答える