我如何添加一个向量,其中我从成对的个体中折叠分数?

时间:2016-06-18 14:50:43

标签: r

我做了一个实验,参与者与另一个参与者成对地解决了一项任务。然后,每个参与者都获得了他们完成任务的得分。对经历了不同程度的试验。

我有一个类似于下面的数据框:

participant <- c(1,1,2,2,3,3,3,4,4,4,5,6)
pair <- c(1,1,1,1,2,2,2,2,2,2,3,3)
trial <- c(1,2,1,2,1,2,3,1,2,3,1,1)
score <- c(2,3,6,3,4,7,3,1,8,5,4,3)
data <- data.frame(participant, pair, trial, score)

participant pair trial score
        1    1     1     2
        1    1     2     3
        2    1     1     6
        2    1     2     3
        3    2     1     4
        3    2     2     7
        3    2     3     3
        4    2     1     1
        4    2     2     8
        4    2     3     5
        5    3     1     4
        6    3     1     3

我想在数据框中添加一个新的向量,其中每个参与者在每个试验中得到他们自己的得分与其他参与者得分之间的数字差异

是否有人知道如何做到这一点?

最终应该看起来像这样:

participant pair trial score difference
    1        1     1     2       4
    1        1     2     3       0
    2        1     1     6       4
    2        1     2     3       0
    3        2     1     4       3
    3        2     2     7       1
    3        2     3     3       2
    4        2     1     1       3
    4        2     2     8       1
    4        2     3     5       2
    5        3     1     4       1
    6        3     1     3       1

2 个答案:

答案 0 :(得分:3)

这是一个解决方案,涉及首先重新排序data,使得每个连续的行对对应于单个试验中的单个对。这允许我们对diff()进行一次调用以提取差异:

data <- data[order(data$trial,data$pair,data$participant),];
data$diff <- rep(diff(data$score)[c(T,F)],each=2L)*c(-1L,1L);
data;
##    participant pair trial score diff
## 1            1    1     1     2   -4
## 3            2    1     1     6    4
## 5            3    2     1     4    3
## 8            4    2     1     1   -3
## 11           5    3     1     4    1
## 12           6    3     1     3   -1
## 2            1    1     2     3    0
## 4            2    1     2     3    0
## 6            3    2     2     7   -1
## 9            4    2     2     8    1
## 7            3    2     3     3   -2
## 10           4    2     3     5    2

我以为你想要标志来捕捉差异的方向。因此,举例来说,如果一个参与者在同一个试验对中的另一个参与者得分低于 4分那么我认为你会想要-4。如果您想要所有正值,可以将乘法移除c(-1L,1L)并添加对abs()的调用:

data$diff <- rep(abs(diff(data$score)[c(T,F)]),each=2L);
data;
##    participant pair trial score diff
## 1            1    1     1     2    4
## 3            2    1     1     6    4
## 5            3    2     1     4    3
## 8            4    2     1     1    3
## 11           5    3     1     4    1
## 12           6    3     1     3    1
## 2            1    1     2     3    0
## 4            2    1     2     3    0
## 6            3    2     2     7    1
## 9            4    2     2     8    1
## 7            3    2     3     3    2
## 10           4    2     3     5    2

这是围绕ave()构建的解决方案,不需要首先重新排序整个data.frame:

data$diff <- ave(data$score,data$trial,data$pair,FUN=function(x) abs(diff(x)));
data;
##    participant pair trial score diff
## 1            1    1     1     2    4
## 2            1    1     2     3    0
## 3            2    1     1     6    4
## 4            2    1     2     3    0
## 5            3    2     1     4    3
## 6            3    2     2     7    1
## 7            3    2     3     3    2
## 8            4    2     1     1    3
## 9            4    2     2     8    1
## 10           4    2     3     5    2
## 11           5    3     1     4    1
## 12           6    3     1     3    1

以下是如何获得同一试验对中其他参与者的得分:

data$other <- ave(data$score,data$trial,data$pair,FUN=rev);
data;
##    participant pair trial score other
## 1            1    1     1     2     6
## 2            1    1     2     3     3
## 3            2    1     1     6     2
## 4            2    1     2     3     3
## 5            3    2     1     4     1
## 6            3    2     2     7     8
## 7            3    2     3     3     5
## 8            4    2     1     1     4
## 9            4    2     2     8     7
## 10           4    2     3     5     3
## 11           5    3     1     4     3
## 12           6    3     1     3     4

或者,假设data.frame已根据初始解决方案重新排序:

data$other <- c(rbind(data$score[c(F,T)],data$score[c(T,F)]));
data;
##    participant pair trial score other
## 1            1    1     1     2     6
## 3            2    1     1     6     2
## 5            3    2     1     4     1
## 8            4    2     1     1     4
## 11           5    3     1     4     3
## 12           6    3     1     3     4
## 2            1    1     2     3     3
## 4            2    1     2     3     3
## 6            3    2     2     7     8
## 9            4    2     2     8     7
## 7            3    2     3     3     5
## 10           4    2     3     5     3

替代方案,使用matrix()代替rbind()

data$other <- c(matrix(data$score,2L)[2:1,]);
data;
##    participant pair trial score other
## 1            1    1     1     2     6
## 3            2    1     1     6     2
## 5            3    2     1     4     1
## 8            4    2     1     1     4
## 11           5    3     1     4     3
## 12           6    3     1     3     4
## 2            1    1     2     3     3
## 4            2    1     2     3     3
## 6            3    2     2     7     8
## 9            4    2     2     8     7
## 7            3    2     3     3     5
## 10           4    2     3     5     3

答案 1 :(得分:3)

以下是使用data.table的选项:

library(data.table)
setDT(data)[,difference := abs(diff(score)), by = .(pair, trial)]
data
#    participant pair trial score difference
# 1:           1    1     1     2          4
# 2:           1    1     2     3          0
# 3:           2    1     1     6          4
# 4:           2    1     2     3          0
# 5:           3    2     1     4          3
# 6:           3    2     2     7          1
# 7:           3    2     3     3          2
# 8:           4    2     1     1          3
# 9:           4    2     2     8          1
#10:           4    2     3     5          2
#11:           5    3     1     4          1
#12:           6    3     1     3          1

稍快一点的选择是:

setDT(data)[, difference := abs((score - shift(score))[2]) , by = .(pair, trial)]

如果我们需要另一对的价值:

data[, other:= rev(score) , by = .(pair, trial)]
data
#    participant pair trial score difference other
# 1:           1    1     1     2          4     6
# 2:           1    1     2     3          0     3
# 3:           2    1     1     6          4     2
# 4:           2    1     2     3          0     3
# 5:           3    2     1     4          3     1
# 6:           3    2     2     7          1     8
# 7:           3    2     3     3          2     5
# 8:           4    2     1     1          3     4
# 9:           4    2     2     8          1     7
#10:           4    2     3     5          2     3
#11:           5    3     1     4          1     3
#12:           6    3     1     3          1     4

或使用dplyr

library(dplyr)
data %>%
    group_by(pair, trial) %>% 
    mutate(difference = abs(diff(score)))
#   participant  pair trial score difference
#         <dbl> <dbl> <dbl> <dbl>      <dbl>
#1            1     1     1     2          4
#2            1     1     2     3          0
#3            2     1     1     6          4
#4            2     1     2     3          0
#5            3     2     1     4          3
#6            3     2     2     7          1
#7            3     2     3     3          2
#8            4     2     1     1          3
#9            4     2     2     8          1
#10           4     2     3     5          2
#11           5     3     1     4          1
#12           6     3     1     3          1