计算数据帧中每个个体变量的变化次数
可能是一个非常简单的问题,但我很难在r中解决这个问题。 我有一个包含四个变量的数据集:ID(用于识别参与者),Type(此次具有1个值),Decision(A或B)和Feedback(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...
非常感谢您对您的帮助提前。
这最好在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与'head'和'tail'。我用'embed'也有类似的答案,但是这个更清晰。 – 2013-03-27 16:10:44
@David Robinson非常快速的答复感谢。我需要一些时间来充分理解您的解决方案,因为结果似乎不正确。例如,在ID = 1中,有3次停留和1次班次。但我想,我现在可以弄清楚了。非常感谢!! – user2205323 2013-03-27 16:26:38
@ user2205323:你说你只想在以前的反馈是'1'的情况下停留和转移(这不就是为什么你有代码'mydf $ Feedback [i-1] == 1'吗?)在这种情况下,我相信我给出的输出是正确的 – 2013-03-27 16:37:28
如何通过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
这是使用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
你可以发布'dput(head(mydf,50))'的结果吗?这会创建数据框的前50行的可重复版本,并使它更容易回答? – 2013-03-27 15:25:44
这些反馈因素如何与他们留在A或B中? – Chase 2013-03-27 15:33:44
对于你所示的例子,对于'ID = 1',你能解释'stay'和'shift'是什么吗? – Arun 2013-03-27 15:38:18