【问题标题】:Conditional column creation (horizontal and vertical conditions)条件列创建(水平和垂直条件)
【发布时间】:2013-12-08 21:12:01
【问题描述】:

我的起始条件类似于df 数据框

df<-data.frame(id=c(rep(2, 3), rep(4, 2)), year=c(2005:2007, 2005:2006), event=c(1,0,0,0,1))

  id year event
1  2 2005     1
2  2 2006     0
3  2 2007     0
4  4 2005     0
5  4 2006     1

我有一系列演员(通过 id 识别),他们碰巧在某一年经历了一个事件。

我在这里尝试构建一系列附加列,描述 a) 与事件的距离和 b) 这种距离是否可观察。

这是我想要的。

   id year event evm2 evm1 evp1 evp2 ndm2 ndm1 ndp1 ndp2
1  2 2005     1    0    0    0    0    1    1    0    0
2  2 2006     0    0    1    0    0    1    0    0    1
3  2 2007     0    1    0    0    0    0    0    1    1
4  4 2005     0    0    0    1    0    1    1    0    1
5  4 2006     1    0    0    0    0    1    0    1    1

event 在某年有事件时等于 1。 evm1 等于 1,当事件在前一年可观察到时。同样,当事件发生在下一年时,evp1 为 1 - 字母 pm 代表“加号”和“减号”,数字代表距该事件的年数。 对于其中一些观测,距离是不可观测的,因为可用时间窗太短。 df[1,] 就是这种情况,我们不知道前几年是否发生过事件。在这种情况下,ndm1ndm2 被编码为 1。如果我们考虑df[5,] 的情况,则ndp1(和ndp2)将被编码为 1。 evnd 变量的工作方式完全相同。但前者告诉在一定距离上是否有事件,后者则揭示这样的距离是否实际上是可观察到的。

我尝试使用以下嵌套的 for 循环来完成此操作,但没有成功。

lag<-c(-2, -1, 1, 2)
df2<-df
df2[,4:11]<-0
colnames(df2)<-c("id", "year", "event", "evm2",  "evm1",  "evp1",  "evp2",  "ndm2",  "ndm1",  "ndp1",  "ndp2") 


for (i in length(df2$id)) {

  id<-df2[i,1]
  yr<-df2[i,2]
  sta<-3
  sta2<-7

  for (j in lag){

    sta<-sta+1
    sta2<-sta2+1

    if !is.null(df2[df2$id==id & df2$year==yr+j])==TRUE {

      rw<-which(df2[df2$id==id & df2$year==yr+j])

      if (df2[rw,3]==1) df2[i, sta]==1

    } else {

      df2[i, sta2]==1

    }

  }

}

您是否发现任何可能导致错误的原因?我已经疯了两天试图让它发挥作用,如果你能提供帮助,我将非常感激。

【问题讨论】:

  • 您在if 周围缺少括号,这是第一件事。而且您不需要使用TRUE 测试是否相等。应该是:if (!is.null(df2[df2$id==id &amp; df2$year==yr+j])) 但是,我不确定这是唯一的问题。
  • 是否可以假设对于给定的id,您始终拥有一组至少两个连续且已排序的年份的数据?如果是这样,我可以展示一个简短的矢量化解决方案。
  • @musically_ut 非常感谢您的评论。你完全正确。仍然不起作用的是哪个功能。你知道为什么吗?

标签: r for-loop if-statement


【解决方案1】:

根据我的评论,这是我想到的可能重写的内容:

lag.it <- function(x, n = 0L) {
  l <- length(x)
  neg.lag <- min(max(0L, -n), l)
  pos.lag <- min(max(0L, +n), l)
  c(rep(NA, +neg.lag),
    head(x, -neg.lag),
    tail(x, -pos.lag),
    rep(NA, +pos.lag))
}

library(plyr)
ddply(df, "id", transform,
      evm2 = lag.it(event, -2),
      evm1 = lag.it(event, -1),
      evp1 = lag.it(event, +1),
      evp2 = lag.it(event, +2))

#   id year event evm2 evm1 evp1 evp2
# 1  2 2005     1   NA   NA    0    0
# 2  2 2006     0   NA    1    0   NA
# 3  2 2007     0    1    0   NA   NA
# 4  4 2005     0   NA   NA    1   NA
# 5  4 2006     1   NA    0   NA   NA

注意我是如何使用NAs 而不是使用两组变量的。虽然我建议您保持这种方式,但您可以通过定义例如轻松获得您所要求的内容。 ndm2is.na(evm2) 然后将 NAs 替换为零。

【讨论】:

  • 我真的认为这个解决方案是天才。它太聪明了,我可能没有完全理解它(特别是我不理解 neg.lag 和 pos.lag 的定义)。你介意给我解释一下吗?为了回答你上面的问题,我的一些观察可以在 7 年内观察到,而其他观察只能在更短的时间内观察到——其中一些只是 1 年。无论如何,我会考虑 +/-2 年的延迟来创建额外的变量。非常感谢您的帮助。
  • 根据滞后 n 的符号(正数或负数),您需要在向量的开头或结尾添加(正数)NA。这就是为什么我依赖两个变量 neg.lagpos.lag 但根据定义,这两个变量中只有一个是非零的。很高兴你喜欢那个解决方案。如果它解决了您的问题,请考虑支持并接受它。
  • 已接受解决方案。我已经投了赞成票。我仍然不清楚一个非常小的细节。为什么写 0L 而不是简单地写 0?再次感谢。 R 编码风格的精彩课程。
  • 我终于尝试了您的程序,但它会产生错误。我将滞后时间延长到 +/- 7 年,并且一旦遇到观察次数较少的 id(例如两年),它就会说“参数意味着不同的行数:2、7、6、5、4、3 ”。你能说出它为什么这么说吗?你能想象一个解决方案吗?非常非常感谢!
  • 我的数据框很大,例程还没有完成。然而,在较小的数据集上,它似乎工作得很好。最终,我按照plyr 包的作者的建议将transform 替换为mutate。再次感谢您的宝贵支持。
猜你喜欢
  • 2023-01-29
  • 2012-03-22
  • 2010-09-20
  • 2021-10-19
  • 1970-01-01
  • 1970-01-01
  • 2012-11-14
  • 2014-09-21
  • 1970-01-01
相关资源
最近更新 更多