使用R中的一些规则创建一个新变量

时间:2017-08-18 20:49:45

标签: r

下面的dat1包含三个变量。有三个唯一的ID,每个都有多个记录。

ID <- c(rep(1,7), rep(2,6), rep(3,5))
t <- c(seq(1,7), seq(1,6), seq(1,5))
y <- c(rep(6,7), rep(1,6), rep(6,5))
z <- c(6,NA,NA,NA,NA,NA,NA,1,NA,NA,NA,NA,NA,6,NA,NA,NA,NA)
randn <- rnorm(18,0,1)
dat1 <- data.frame(ID, t, y, z, randn)

请注意,对于每个ID,当t为最小值时,z的值不会丢失(每个ID的第一行)。

我需要创建一个名为NewX的新列。注意,数据帧中的每个单元可以表示为Cell(i,j),其中i是ID的数量,j是记录的数量。例如,z(1,1)= 6; z(2,1)= 1,依此类推。

  • 案例1:如果j = 1(即每个ID的第一条记录):

    NewX(i,1)= rnorm(n = 1,mean = z(i,1)* randn(i,1),sd = 1)

  • 案例2:如果j> 1(即,不是每个ID的第一个记录)

    NewX(i,j)= rnorm(n = 1,mean = randn(i,j)* z(i,j),sd = 1),其中z(i,j)= z(i,j -1) - NewX(i,j-1)

1 个答案:

答案 0 :(得分:2)

我认为这可以达到你想要的效果。我不是用不同的方式进行大量单独的rnorm调用,而是使用均值0进行单个rnorm,并为每个调用添加均值调整。

首先是一个功能,可以对单个组执行您想要的操作:

foo = function(dat) {
    NewX = rnorm(nrow(dat))
    NewX[1] = NewX[1] + dat$z[1] * dat$randn[1]
    for (i in 2:nrow(dat)) {
        dat$z[i] = dat$z[i - 1] - NewX[i - 1]
        NewX[i] = NewX[i] + dat$randn[i] * dat$z[i]
    }
    dat$NewX = NewX
    return(dat)
}

将该功能应用于每个组:

# using base:
do.call(rbind, args = lapply(split(dat1, dat1$ID), foo))

# using dplyr
library(dplyr)
group_by(dat1, ID) %>% do(foo(.))
# # A tibble: 18 x 6
# # Groups:   ID [3]
#       ID     t     y          z      randn       NewX
#    <dbl> <int> <dbl>      <dbl>      <dbl>      <dbl>
#  1     1     1     6  6.0000000  0.9613432  7.4952847
#  2     1     2     6 -1.4952847 -1.3119847  1.8228137
#  3     1     3     6 -3.3180984  0.4025080 -1.2172146
#  4     1     4     6 -2.1008838 -1.8188487  5.8479404
#  5     1     5     6 -7.9488242  0.6298387 -3.5717586
#  6     1     6     6 -4.3770656 -0.6872249  3.2324739
#  7     1     7     6 -7.6095394 -0.5542710  2.8111069
#  8     2     1     1  1.0000000 -0.1773999 -0.7477932
#  9     2     2     1  1.7477932 -1.8299770 -3.1449473
# 10     2     3     1  4.8927405  0.2852126  1.8376771
# 11     2     4     1  3.0550633 -0.5352681 -2.4578430
# 12     2     5     1  5.5129063 -0.6147433 -3.3131580
# 13     2     6     1  8.8260643 -0.3065883  0.3074687
# 14     3     1     6  6.0000000  1.6159438 10.4165718
# 15     3     2     6 -4.4165718  1.1954419 -6.0555754
# 16     3     3     6  1.6390036 -1.1659655 -4.3974029
# 17     3     4     6  6.0364065  0.9377918  6.3873113
# 18     3     5     6 -0.3509048 -1.1887718  0.6909987