使用R中的一些规则创建一个新变量
下面的dat1包含三个变量。有三个唯一的ID,每个ID都有多个记录使用R中的一些规则创建一个新变量,r,R,下面的dat1包含三个变量。有三个唯一的ID,每个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 &l
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我想这是你想要的。我没有使用不同的方法进行大量的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
#使用base:
调用(rbind,args=lappy(split(dat1,dat1$ID),foo))
#使用dplyr
图书馆(dplyr)
分组依据(dat1,ID)%>%do(foo()
##tibble:18 x 6
##组:ID[3]
#ID t y z randn NewX
#
# 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
我想这是你想要的。我没有使用不同的方法进行大量的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
#使用base:
调用(rbind,args=lappy(split(dat1,dat1$ID),foo))
#使用dplyr
图书馆(dplyr)
分组依据(dat1,ID)%>%do(foo()
##tibble:18 x 6
##组:ID[3]
#ID t y z randn NewX
#
# 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
您的符号令人困惑。您应该(i)使用set.seed创建一个可复制的示例,并(ii)明确显示该示例的预期输出(除了描述其背后规则的文字)。如果NewX
是一列,它怎么可能有行和列?你是说这是一个新表吗?OP是滥用符号,用“i”表示组(ID),用“j”表示行。忽略所有的i,
s,而是在每个ID内思考。。。另外,在OP的例子中,j
和t
是等价的。您的符号很混乱。您应该(i)使用set.seed创建一个可复制的示例,并(ii)明确显示该示例的预期输出(除了描述其背后规则的文字)。如果NewX
是一列,它怎么可能有行和列?你是说这是一个新表吗?OP是滥用符号,用“i”表示组(ID),用“j”表示行。忽略所有的i,
s,而是在每个ID内思考。。。同样,在OP的例子中,j
和t
是等价的。