繁体   English   中英

R循环,用于匹配的data.table列

[英]R Loop for matched data.table columns

我真的很难创建一个运行模型的函数,其中所有变量abdgN都有多个版本,如data.table中所示,在下面我将其命名为crm

crm = data.table(
  East = 26500,
  North = c(115000, 120000, 125000, 130000, 135000, 140000), 
  rain = c(1049.61, 1114.31, 1361.61, 1407.2, 1499.56, 1654.13), 
  crop = 'Wheat', area = c(0.1718, 0.1629, 0.1082, 0.0494, 0.02, 0.004), 
  rn = c("10007", "10018", "10023", "10024", "10025", "10026"), 
  N1 = 184.262648839489, N2 = 180.312874871521, N3 = 178.615847839997,
  N4 = 182.531626054579, a1 = 0.186117715072018, a2 = -0.0232731908915799,
  a3 = 0.227017532149122, a4 = 0.162943230565506, b1 = 0.000478900233700419,
  b2 = 0.000787931973696371, b3 = 0.000458478256537521, b4 = 0.000517304324750896,
  d1 = -0.000328164576390286, d2 = -0.000112122093240884, d3 = 0.000112702113716146,
  d4 = 7.40875908059628e-05, g1 = 4.04709473710477e-06, g2 = 3.68724096485995e-06,
  g3 = 3.47214450131546e-06, g4 = 3.55825543257538e-06, key = 'rn'
)

我想做的是运行下面的函数来计算lnN的值,并将其放入与标题中与输入模型的变量具有相同编号的列中。 即使用a1b1d1g1N1将生成lnN1列,依此类推,对于所有2s,3s和4s。

n <- 1:4
cols <- paste0("lnN",n)
for(i in 1:length(n)){
crm[,(cols) := lapply(.SD ,function (x) {
  N = crm[,7+i]
  a = crm[,11+i]
  b = crm[,15+i]
  d = crm[,19+i]
  g = crm[,23+i]
a + (b*crm[,rain]) + (g*N) + (d*crm[,rain]*N)}), .SDcols = paste0("N",n)]

}

我还没有找到有关如何完成此操作的示例。 我尝试使用mapply但看不到如何在每个变量的所有迭代中迭代mapply。 谢谢您的帮助!

怎么样:

library(dplyr)
cbind(crm, do.call(cbind, 
  lapply(1:4, function(x) {
    select(crm, c(contains(as.character(x)), rain)) %>% 
      setnames(gsub("[0-9]", "", names(.))) %>%
      transmute(lnN = a + (b*rain) + (g*N) + (d*rain*N)) %>%
      setnames(paste0("lnN", x))
  })
))

主要思想是,对于每个数字,仅选择包含该数字的列(还包括rain ),重命名这些列以删除数字,应用公式,重命名结果列以附加该数字,然后将结果cbind到原始表。

因此,看了上面的评论后,我发现尝试将迭代次数更改为数千时可能会出现问题,因为Frank和Weihuang都建议我重新考虑如何构造数据。

相反,我要做的是将随机生成的变量矩阵保留为单独的数据框。 e包含多元随机值abgdN (现在称为Nit )在rnm 因此, crm现在只有前六列。 代码如下:

for(i in 1:n){
  a = e[1,i]
  b = e[2,i]
  g = e[3,i]
  d = e[4,i]
Nit = rnm[i]
bob = a + (b*crm$rain) + (g*Nit) + (d*crm$rain*Nit)
data.y <- cbind(data.y, bob)
}
crm <- cbind(crm, data.y)
names(crm)[c(7:n)] = names(bobs)

对于1:n的每次迭代,它将读取每个参数的i值(所有1s,所有2s等),并将其放入模型中,并创建一个名为bob的列。 然后将bob合并到我在函数( data.y )之前创建的空数据框中。 这样循环直到达到所需的循环次数。

然后,我使用cbind将两者合并在一起,然后使用存储在数据框bobs中的名称顺序重命名所有bob列,该数据帧包含从.csv文件读取的列标题为bob.1bob.n的列标题的列表我用Excel制作。

这里有一个melt -和- dcastrecast )版本借力新实施的功能meltpatterns利用提供的名称。 有关说明,请参阅安装Wiki ,因为这是当前正在开发中的功能。

library(data.table) 1.10.5+
# create character version of 1:N (Number of output columns)
N = paste0(seq_len(length(grep('^b', names(crm)))))
# join crm to a melt & recast version of itself using rain as 
#   the join key (note this will fail if the amount of rain may
#   not be unique -- in this case, we should include some ID in
#   id.vars, like rn, and adjust accordingly)
crm = crm[crm[ , melt(.SD, id.vars = 'rain', 
                      measure.vars = patterns(N = '^N[0-9]', a = '^a[0-9]', 
                                              b = '^b', d = '^d', g = '^g'))
               # use the formula to generate ln
               ][ , ln := a + b*rain + g * N + d * rain * N
                  # reshape wide
                  ][ , dcast(.SD, rain ~ variable, value.var = 'ln')
                     # rename the columns here
                     ][ , setnames(.SD, N, paste0('ln', N))],
          on = 'rain']

# by-reference version
crm[crm[ , melt(.SD, id.vars = 'rain', 
                measure.vars = patterns(N = '^N[0-9]', a = '^a[0-9]', 
                                        b = '^b', d = '^d', g = '^g'))
         # use the formula to generate ln
         ][ , ln := a + b*rain + g * N + d * rain * N
            # reshape wide
            ][ , dcast(.SD, rain ~ variable, value.var = 'ln')],
    # mget tends to be sort of slow, which is why I used the
    #   assign-by-copy approach first above; in larger examples,
    #   this slow-down may be outweighed by the cost of copying
    paste0('ln', N) := mget(N), on = 'rain']

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM