【问题标题】:How to assign a value to a column of a df using values from a vector according to a value in another df如何根据另一个df中的值使用向量中的值将值分配给df的列
【发布时间】:2020-05-26 10:23:38
【问题描述】:

我正在模拟种植园的生长。

我必须在每年(第 0 年到第 6 年的列)中填充 10 棵树(每行一棵)的体积。 我有一个来自“growthmodels”包的函数,它计算每年树的体积,或者创建一个包含一系列年份范围内所有值的向量。 我有一个 df 每年每棵树的年龄(有些树死了,必须重新种植,所以它们的年龄从零开始)。

这是问题的简化版本:

volume <- data.frame(matrix(ncol = 6, nrow = 10))
age <- data.frame("y0" = rep(0, 10))
for (y in 2:6){
        d <- sample(1:10, 1)
        d0 <- 10-d
        age <- cbind(age, c(age[1:d, y-1] + rep(1, d), rep(0, d0)))
        names(age)[y] <- paste0("y", y-1)
}
library(growthmodels)
growth <- chapmanRichards(t=1:5, alpha=3, m=.4, k=.4, beta=1)

我找到了以下方法,但是执行起来超级超级慢。想象一下,我必须为更多的物种和 100 个具有多种增长速度的随机案例运行它。你有什么建议吗?

#inputing normal growth
for (y in 2:6){
        for (t in 1:nrow(volume)) {
                volume[t,y] <- chapmanRichards(t=age[t,y], alpha=3*d, m=.4, k=.4*l, beta=1)
        }
}

我需要保持循环 for (y in 2:6),因为每年 chapmanRichards 公式中的因子 d 和 l 都有不同的值。

【问题讨论】:

  • 我的第一个冲动是使用chapmanRichards 函数的矢量化版本:Vectorize(chapmanRichards, vectorize.args = list("t"))

标签: r loops assign


【解决方案1】:

Base-R 中的类似内容给出的结果与您的循环相同。

apply(age,2, function(y) sapply(y,function(x) chapmanRichards(t=x, alpha=3, m=.4, k=.4, beta=1) ))

      y0        y1        y2       y3        y4       y5
 [1,]  0 0.4720002 1.1098773 1.650880 2.0600919 2.354331
 [2,]  0 0.4720002 1.1098773 1.650880 2.0600919 2.354331
 [3,]  0 0.4720002 1.1098773 1.650880 2.0600919 2.354331
 [4,]  0 0.0000000 0.4720002 1.109877 1.6508796 2.060092
 [5,]  0 0.0000000 0.4720002 0.000000 0.4720002 1.109877
 [6,]  0 0.0000000 0.4720002 0.000000 0.4720002 1.109877
 [7,]  0 0.0000000 0.4720002 0.000000 0.4720002 0.000000
 [8,]  0 0.0000000 0.0000000 0.000000 0.4720002 0.000000
 [9,]  0 0.0000000 0.0000000 0.000000 0.0000000 0.000000
[10,]  0 0.0000000 0.0000000 0.000000 0.0000000 0.000000

编辑:解决您的评论:

你可以做到这一点

rbind(
    apply(age[1:3,],2, chapmanRichards, alpha=3, m=.4, k=.4, beta=1),
    apply(age[4:6,],2, chapmanRichards, alpha=3, m=.4, k=.4*7, beta=1),
    apply(age[7:10,],2, chapmanRichards, alpha=3, m=.4, k=0, beta=1)
)

更新到最新评论:

t(
cbind(
    apply(age[1:3,],1, chapmanRichards, alpha=3, m=.4, k=.4, beta=1),
    apply(age[4:6,],1, chapmanRichards, alpha=3, m=.4, k=.4*7, beta=1),
    apply(age[7:10,],1, chapmanRichards, alpha=3, m=.4, k=0, beta=1)
)
)

   y0        y1       y2        y3       y4        y5
1   0 0.4720002 1.109877 1.6508796 2.060092 2.3543308
2   0 0.4720002 0.000000 0.4720002 0.000000 0.4720002
3   0 0.4720002 0.000000 0.4720002 0.000000 0.4720002
4   0 0.0000000 0.000000 2.7021553 0.000000 2.7021553
5   0 0.0000000 0.000000 0.0000000 0.000000 2.7021553
6   0 0.0000000 0.000000 0.0000000 0.000000 2.7021553
7   0 0.0000000 0.000000 0.0000000 0.000000 0.0000000
8   0 0.0000000 0.000000 0.0000000 0.000000 0.0000000
9   0 0.0000000 0.000000 0.0000000 0.000000 0.0000000
10  0 0.0000000 0.000000 0.0000000 0.000000 0.0000000

【讨论】:

  • 太棒了!如果你必须使用多个增长函数,你会如何塑造它?例如:上面的公式从第1行到第3行,从k=.4*7形成4到7,从8到10为0。
  • 我已经编辑了我的答案以包含一个可能的解决方案。很难确定这是否给出了您想要的结果,因为我对 chapmanRichards 函数一无所知。
  • 我还从您的一个示例中注意到该函数接受向量,考虑到这一点,我编辑部分中的代码已被简化。更改后它应该运行得更快。
  • 用cbind可以做到吗?当我的大循环分析每年发生的事情并计算每列的体积
  • 所以apply( ... , 2, ...) 将数据逐个传递给 chapmanRichards col。如果您正在寻找逐行执行,那么您需要apply(..., 1, ...)。我已经对答案添加了更新
猜你喜欢
  • 2020-12-29
  • 2019-11-02
  • 2016-09-19
  • 2020-09-16
  • 2019-12-22
  • 1970-01-01
  • 2020-09-03
  • 2012-10-12
  • 2022-06-10
相关资源
最近更新 更多