2012-11-23 55 views
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循環。

回答

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 
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 
1

我將使用Roland選擇的「分數」。既然你提到你可以將分數表修改爲2×2的矩陣,我提供了下面的解決方案,與其他2的解決方案有不同的分數數據結構。

讓我解釋一下我的邏輯之前,我爲您提供的代碼:

  1. 我希望通過排
  2. 處理DF行對於每一行,我希望用得分每題選擇的答案
  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 

現在,你可以看到,我需要選擇列名第一個索引得分&行的第二個指數值。因此,如果我能得到分數[[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行(使用rowsums等)。我確信像Sven這樣的經驗豐富的人可以將上面的代碼改進爲一些漂亮的代碼。將不勝感激輸入。