在ddply中运行自定义循环

时间:2013-11-03 05:03:58

标签: r for-loop plyr conditional-statements

我的数据集大约有54,000行。我想将值(First_Pass)设置为T或F,具体取决于另一列中的值以及之前是否已看到其他列的值。我有一个for循环,它完全符合我的需要。但是,该循环仅适用于数据的子集。我需要根据因子级别为不同的子集单独运行循环。

这似乎是plyr函数的完美案例,因为我想将数据拆分为子集,应用函数(我的for循环)然后重新加入数据。但是,我无法让它发挥作用。首先,我给出一个名为char.data的df示例。

     session_id list Sent_Order Sentence_ID Cond1 Cond2 Q_ID   Was_y CI CI_Delta character tsle tsoc Direct
5139          2    b          9          25    rc    su   25 correct  1        0         T  995   56      R
5140          2    b          9          25    rc    su   25 correct  2        1         h   56   56      R
5141          2    b          9          25    rc    su   25 correct  3        1         e   56   56      R
5142          2    b          9          25    rc    su   25 correct  4        1             56   37      R

那里有一些混乱。关键列是session_id,Sentence_ID,CI和CI_Delta。

然后我将名为First_Pass的列初始化为“F”

char.data $ First_Pass< - “F”

我想现在计算每个session_id和Sentence_ID组合的First_Pass实际上是“T”。我创建了一个玩具集,它只是一个子集来计算整体逻辑。这是for循环的代码,它给了我想要的玩具数据。

char.data.toy$First_Pass <- "F"
l <-c(200)
for (i in 1:nrow(char.data.toy)) {
  if(char.data.toy[i,]$CI_Delta >= 0 & char.data.toy[i,]$CI %nin% l){
    char.data.toy[i,]$First_Pass <- "T"
    l <- c(l,char.data.toy[i,]$CI)}
}

我现在想要接受这个循环并为每个session_id和Sentence_ID子集运行它。我创建了一个名为set_fp的函数,然后在ddply中调用它。这是代码:

#define function
set_fp <- function (df){

  l <- 200
  for (i in 1:nrow(df)) {
    if(df[i,]$CI_Delta >= 0 & df[i,]$CI %nin% l){
      df[i,]$First_Pass <- "T"
      l <- c(l,df[i,]$CI)}
    else df[i,]$First_Pass <- "F"
    return(df)
  }

}

char.data.fp <- ddply(char.data,c("session_id","Sentence_ID"),function(df)set_fp(df))

不幸的是,这不太对。很长一段时间,我得到了First_Pass的所有“F”值。现在我得到24 T值,当它应该更多时,所以我怀疑,它只保留最后一个子集或类似的东西。帮助

1 个答案:

答案 0 :(得分:0)

仅使用您提供的四行测试有点困难。我创建了随机数据,看看它是否有效,它似乎对我有用。也可以试试你的数据。

这使用data.table库,不会尝试在loops内运行ddply。我假设手段并不重要。

library(data.table)
dt <- data.table(df)  
l <- c(200)

# subsetting to keep only the important fields
dt <- dt[,list(session_id, Sentence_ID, CI, CI_Delta)]

# Initialising First_Pass    
dt[,First_Pass := 'F']

# The next two lines are basically rewording your logic -

# Within each group of session_id, Sentence_ID, identify the duplicate CI entries. These would have been inserted in l. The first time occurence of these CI entries is marked false as they wouldn't have been in l when that row was being checked 
dt[CI_Delta >= 0,duplicatedCI := duplicated(CI), by = c("session_id", "Sentence_ID")]

# So if the CI value hasn't occurred before within the session_id,Sentence_ID group, and it doesn't appear in l, then mark it as "T"
dt[!(CI %in% l) & !(duplicatedCI), First_Pass := "T"]

# Just for curiosity's sake, calculating l too
l <- c(l,dt[duplicatedCI == FALSE,CI])