【问题标题】:Calculate number of changes of a variable per individual in a data frame计算数据框中每个人的变量更改次数
【发布时间】:2013-03-27 15:23:57
【问题描述】:

可能是一个非常简单的问题,但我很难在 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(Stay)还是 B(Shift)。因此,对于一位参与者,我的代码如下:

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

非常感谢您提前提供的帮助。

【问题讨论】:

  • 您能否发布dput(head(mydf, 50)) 的结果,这将创建数据框前 ​​50 行的可重现版本并使其更容易回答?
  • 反馈如何影响他们留在 A 还是 B?
  • 对于您展示的示例,对于ID=1,您能解释一下stayshift 是什么吗?
  • Stay 和 Shift 是值。如果参与者选择 A,他/她会收到 pos 或 neg 反馈。根据反馈,他/她可以决定再次选择 A(这是停留)或选择其他选项(这将是一个转变)。我想统计实验期间的停留和轮班次数。
  • 所以在ID=1的情况下,有5次试验,第二次是停留,因为参与者最初选择A后选择了A,但第三次决定是转变,因为他/她选择了B。接下来的两个决定也是停留。

标签: r for-loop


【解决方案1】:

最好使用plyr 包中的ddply 完成此操作(您必须安装它),它会根据其中一列拆分数据框并对每一列进行一些分析,然后再组合成一个新数据框。

首先,编写一个函数num.stay.shift,在给定数据框的单个子集(在 cmets 中解释)的情况下计算您的停留和移位值:

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 与 headtail 一起使用。我使用embed 得到了类似的答案,但这更干净。
  • @David Robinson 感谢您的快速回答。我需要一些时间来完全理解您的解决方案,因为结果似乎不正确。例如,在 ID=1 中,有 3 次停留和 1 次班次。但我想,我现在可以弄清楚了。非常感谢!!
  • @user2205323:您说您只需要在之前的反馈为1 的情况下才需要停留和换班(这不就是您有代码mydf$Feedback[i-1]==1 的原因吗?)在那种情况下,我相信我给出的输出是正确的
  • @user2205323:您是否想根据之前的反馈拆分停留和轮班?如果您只想要所有的停留和转移而不考虑反馈,只需将函数的最后一行更改为c(Stay=sum(stay), Shift=sum(!stay))
  • @MatthewPlourde:embed 函数是 R 中隐藏的瑰宝之一。希望在这里看到它的实际应用。
【解决方案2】:

如何按 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

【讨论】:

    【解决方案3】:

    这是使用 embed 函数的一个稍微复杂的替代方法,正如 @DavidRobinson 的回答中提到的 cmets。

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-02
      • 1970-01-01
      • 2021-05-22
      • 1970-01-01
      • 1970-01-01
      • 2020-05-22
      相关资源
      最近更新 更多