计算数据框中每个人的变量的变化数

时间:2013-03-27 15:23:58

标签: r for-loop

可能是一个非常简单的问题,但我很难在r中解决这个问题。 我有一个包含四个变量的数据集:ID(用于标识参与者),类型(此次具有1个值),决策(A或B)和反馈(0或1)。两个参与者的数据集如下所示:

ID   Type    Decision    Feedback
1     1       A           0
1     1       A           0
1     1       B           1
1     1       B           1
1     1       B           0
2     1       A           0
2     1       A           1
2     1       A           1
2     1       A           0
2     1       B           1
etc...

我想根据之前的反馈计算决策过程中的变化数量。换句话说,如果参与者选择A并收到负面反馈,他/他是否会再次选择A(停留)或B(转移)。所以我的代码对于一位参与者来说如下:

Stay=0
Shift=0  

for(i in 2:length(mydf$Type)){  
    if(mydf$Decision[i] == "A" && mydf$Feedback[i-1]==1 && mydf$Decision [i-1] == "A" ){
    Stay= Stay+1
    }
    else if(mydf$Decision [i] == "B" && mydf$Feedback[i-1]==1 && mydf$Decision [i-1] == "B" ){
    Stay= Stay+1
    }
    else if(mydf$ Decision [i] == "A" && mydf$Feedback[i-1]==1 && mydf$Decision [i-1] == "B" ){
    Shift= Shift+1
    }
    else if(mydf$Decision [i] == "B" && mydf$Feedback[i-1]==1 && mydf$Decision [i-1] == "A" ){
    Shift= Shift+1
    }
}

但是,我的数据框包含20个参与者,我不知道如何扩展我的代码以获得每个参与者的停留和轮班次数(即,最后得到这样的内容):

#ID    Stay    Shift
#1     10      10
#2     16      4
#etc...

非常感谢您的帮助。

3 个答案:

答案 0 :(得分:3)

最好使用plyr包中的ddply(您必须安装它),根据其中一个列拆分数据框并对每个列进行一些分析,在重新组合成新数据框之前。

首先,编写一个函数num.stay.shift,根据数据框的单个子集计算您的停留和移位值(在注释中说明):

num.stay.shift = function(d) {
    # vector of TRUE or FALSE for whether d$Feedback is 1
    negative.feedback = (head(d$Feedback, -1) == 1)
    # vector of TRUE or FALSE for whether there is a change at each point
    stay = head(d$Decision, -1) == tail(d$Decision, -1)
    # summarize as two values: the number that stayed when feedback == 1,
    # and the number that shifted when feedback == 1
    c(Stay=sum(stay[negative.feedback]), Shift=sum(!stay[negative.feedback]))
}

然后,使用ddply将该函数应用于数据框中的每个人,并按ID分割:

print(ddply(tab, "ID", num.stay.shift))

在您显示的数据框的子集上,您最终会得到

#   ID Stay Shift
# 1  1    2     0
# 2  2    2     0

答案 1 :(得分:1)

如何通过ID和反馈进行细分:

  library(data.table)
  X <- data.table(mydf, key="ID")

  X[, list(Dif=abs(diff(as.numeric(Decision))),  
          FB=head(Feedback, -1))
        , by=ID][,list(Shifted=sum(Dif), Stayed=length(Dif)-sum(Dif)), by=list(ID,FB)]

  #     ID FB Shifted Stayed
  #  1:  1  0       1      1
  #  2:  1  1       0      2
  #  3:  2  0       1      1
  #  4:  2  1       0      2

或如果您不想按Feedback进行细分,则更为简洁:

X[ , {Dif=abs(diff(as.numeric(Decision))); 
     list(Shifted=sum(Dif), Stayed=length(Dif)-sum(Dif))}
  , by=list(ID)]

#      ID Shifted Stayed
# 1:  1       1      3
# 2:  2       1      3

答案 2 :(得分:1)

这是使用embed函数的稍微有点替代方法,正如@ DavidRobinson回答的评论中提到的那样。

d<-read.table(text="ID   Type    Decision    Feedback
1     1       A           0
1     1       A           0
1     1       B           1
1     1       B           1
1     1       B           0
2     1       A           0
2     1       A           1
2     1       A           1
2     1       A           0
2     1       B           1", header=TRUE)

do.call(rbind,
    by(d, d$ID, function(x) {
        f <- function(x) length(unique(x)) == 1
        stay <- apply(embed(as.vector(x$Decision), 2), 1, f)
        neg.feedback <- x$Feedback[1:nrow(x)-1] == 1
        c(Stay = sum(stay & neg.feedback), Shift = sum((! stay) & neg.feedback))
    })
)
#   Stay  Shift
# 1    2      0
# 2    2      0