根据组的上一行和下一行的值生成新变量

时间:2014-06-04 19:48:50

标签: r

我正在使用包含多个主题(id)的面板数据,并在不同日期发生事件(first_occurrence)。我的目标是创建一个新变量(result),该变量在first occurrence之前的2天,first occurrence的日期以及{{1}之后的2天内为1 }。

这是一个包含样本数据和所需输出的示例:

first occurrence

虽然这可能不是最有效的解决方案,但我设法让代码在Stata中运行(请参阅下面的Stata代码),虽然我也想让它在R中运行,并且会感谢任何想法的人

谢谢!

Stata代码:

data <- structure(list(id = c(1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 
2, 3, 3, 3, 3, 3, 3, 3), day = c(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 
2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6), first_occurrence = c(0, 0, 
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1), desired_output = c(1, 
1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1)), .Names = c("id", 
"day", "first_occurrence", "desired_output"), row.names = c(NA, 
-21L), class = "data.frame")

2 个答案:

答案 0 :(得分:1)

这是一种方式。您可以使用ave按组查看,然后您可以使用which.max查找第一个匹配项,然后计算该值与所有其他值的距离

close<-(with(data, ave(first_occurrence, id, FUN=function(x) 
    abs(seq_along(x)-which.max(x)))
)<=2)+0

这里我使用+0将逻辑值转换为0/1值。现在,您可以将其与现有数据结合使用

cbind(data, close)

这就是

   id day first_occurrence desired_output close
1   1   0                0              1     1
2   1   1                0              1     1
3   1   2                1              1     1
4   1   3                0              1     1
5   1   4                0              1     1
6   1   5                0              0     0
7   1   6                0              0     0
8   1   7                0              0     0
9   2   0                0              0     0
10  2   1                0              0     0
11  2   2                0              1     1
12  2   3                0              1     1
13  2   4                1              1     1
14  2   5                0              1     1
15  3   0                0              0     0
16  3   1                0              0     0
17  3   2                0              0     0
18  3   3                0              0     0
19  3   4                0              1     1
20  3   5                0              1     1
21  3   6                1              1     1

根据需要。请注意,此方法假定数据按日排序。

答案 1 :(得分:1)

这是使用包dplyr的另一种方法:

require(dplyr)        #install and load the package

data %.%
  arrange(id, day) %.%    # to sort the data by id and day. If it is already, you can remove this row
  group_by(id) %.%
  mutate(n = 1:n(),
         result = ifelse(abs(n - n[first_occurrence == 1]) <= 2, 1, 0)) %.%
  select(-n)

#   id day first_occurrence desired_output result
#1   1   0                0              1      1
#2   1   1                0              1      1
#3   1   2                1              1      1
#4   1   3                0              1      1
#5   1   4                0              1      1
#6   1   5                0              0      0
#7   1   6                0              0      0
#8   1   7                0              0      0
#9   2   0                0              0      0
#10  2   1                0              0      0
#11  2   2                0              1      1
#12  2   3                0              1      1
#13  2   4                1              1      1
#14  2   5                0              1      1
#15  3   0                0              0      0
#16  3   1                0              0      0
#17  3   2                0              0      0
#18  3   3                0              0      0
#19  3   4                0              1      1
#20  3   5                0              1      1
#21  3   6                1              1      1

代码的作用是,首先按id分组然后再添加另一列(n),其中每组的行数从1到每组的行数。然后,它会创建另一个resultifelse来检查当前n(每行)和n first_occurrence之间的绝对差异1.如果该差异等于或小于2,则结果为1,否则为0.最后一行删除列n

编辑:

mutate(n = 1:n())放在group_by

之前可能会更有效率
data %.%
  arrange(id, day) %.%    # to sort the data by id and day. If it is already, you can remove this row
  mutate(n = 1:n()) %.%
  group_by(id) %.%
  mutate(result = ifelse(abs(n - n[first_occurrence == 1]) <= 2, 1, 0)) %.%
  select(-n)