【问题标题】:R Loop: Perform a Function for Every 3 RowsR 循环:每 3 行执行一个函数
【发布时间】:2019-11-16 11:10:49
【问题描述】:

我有 2000 株小麦,在 40 天内生长。 我想对每个植物执行 coeff 函数,以找到 3 个时间点产生的二次方程的系数。 (a, b, 和 c)

(1) coef(lm(y~poly(x,2,raw=TRUE)) 函数完全按照我想要的方式工作。

(2) 但是,我的数据呈现方式需要我手动设置 x 和 y。

(3) 因此,我融化了我的数据,并订购了它。

(4) 我想创建一个循环,将“Day”列中的前三个设置为 x。然后我希望它取“高度”列中的前三个并将其设置为 y。

那我想执行 coeff 函数。

最后我希望它显示我需要的系数输出,最好是在一个新的数据表中。

然后对所有小麦植物每三行重复一次,它们代表每个小麦 ID。

1) 这个函数有效,给我系数:a, b, c

x<-c(1,2,3)
y<-c(1,10,4)
coef(lm(y~poly(x,2,raw=TRUE)))

2) 这就是我的数据最初的样子

A = matrix(c(5, 4, 2, 10, 10, 4, 5, 15, 6),nrow=3, ncol=3)
colnames(A)<-c("10", "25", "40")
rownames(A)<-c("Wheat 1", "Wheat 2", "Wheat 3")
A

3) 这是我的融化格式

A.melted<-as.data.frame(melt(A, id.vars="ID"))
A.melted<-A.melted[with(A.melted,order(Var1)),]
colnames(A.melted) <- c("WheatID", "Day", "Height")
A.melted$Day<-as.numeric(as.character(A.melted$Day))
A.melted
#

4) 这就是我想要用我的循环做的事情......

  • 每 3 行,
  • x&lt;-A.melted[,2]
  • y&lt;-A.melted[,3]
  • coef(lm(y~poly(x,2,raw=TRUE)))
  • 编译系数的东西:a、b、c

我只是不熟悉循环的语法,我很想得到任何提示和建议。仔细阅读 Google 告诉我,除非绝对需要,否则不应执行循环,因为我可能会遇到更多问题 - 因此我也对非循环技术持开放态度。

【问题讨论】:

    标签: r loops dataframe data-manipulation


    【解决方案1】:

    如果您想循环执行此操作,请尝试此操作。关键部分是使用seqby = 参数让索引采取您需要的步骤。

    library(tibble)
    
    df <- tibble(
      WheatID = rep(NA_character_, nrow(A)),
      Intercept = rep(NA_real_, nrow(A)),
      poly1 = rep(NA_real_, nrow(A)),
      poly2 = rep(NA_real_, nrow(A))
    )
    cnt <- 1
    for (i in seq(1, nrow(A.melted), by = 3)) {
      x <- A.melted$Day[i + 0:2]
      y <- A.melted$Height[i + 0:2]
      df$WheatID[cnt] <- as.character(A.melted$WheatID[i])
      df[cnt, 2:4] <- coef(lm(y~poly(x,2,raw=TRUE)))
      cnt <- cnt + 1
    }
    df
    

    注意:我不是data.table 的人。因此,我给你一个tibble

    【讨论】:

    • 再次感谢您的回答!但是假设我现在想找到每条二次曲线下的面积?最好的方法是什么?
    • 这个话题与这个问题没有直接关系。找到相对容易的二次多项式的积分函数并在感兴趣的范围内计算它的确切方法。我你不知道,怎么做,请在Mathematics 上提问。还有一种数值方法,即在感兴趣的区域内生成随机点并获得低于多项式的比例。
    【解决方案2】:

    我们可以在 data.table 的帮助下做到这一点,见?data.table:

    library(data.table)
    
    A.models = A.melted[, model := list(.(lm(Height ~ poly(Day, 2), 
                                             data = list(.(.SD[WheatID == .BY[[1]]]))))), 
                        by = WheatID] 
    
    A.models[, coefs := list(.(coefficients(model[[1]]))), 
             by = WheatID]
    

    您可以像这样访问每个模型:

    A.models[WheatID == "Wheat 1", model[[1]]]
    

    甚至

    A.models[WheatID == "Wheat 1", summary(model[[1]])]
    

    这里的神奇之处在于data.table 接受J 表达式,而不仅仅是函数。

    【讨论】:

      【解决方案3】:

      这是你可以用 data.table 包做的事情。

      data.list <- split(A.melted, f = (1:nrow(A.melted) - 1) %/% 3)
      coefs <- lapply(data.list, function(x) {
        coefs <- coef(lm(Day ~ poly(Height, raw=TRUE), data = x))
        data.table(
          intercept = coefs[1],
          poly.height = coefs[2]
        )
      })
      
      coefs <- rbindlist(coefs)
      

      【讨论】:

        【解决方案4】:

        或者你可以直接在原始矩阵上执行apply()

        x <- as.numeric(colnames(A))
        apply(A, 1, function(y) coef(lm(y~poly(x,2,raw=TRUE))))
        
                                    Wheat 1      Wheat 2       Wheat 3
        (Intercept)             -3.88888889 -0.555555556  6.666667e-01
        poly(x, 2, raw = TRUE)1  1.11111111  0.477777778  1.333333e-01
        poly(x, 2, raw = TRUE)2 -0.02222222 -0.002222222 -2.417315e-18
        

        或者您可以转置数据并直接使用coef(...) 调用:

        x <- as.numeric(colnames(A))
        coef(lm(t(A) ~ poly(x, 2, raw = TRUE)))
        

        【讨论】:

          猜你喜欢
          • 2018-12-27
          • 2011-05-14
          • 2021-04-13
          • 2021-01-02
          • 1970-01-01
          • 1970-01-01
          • 2018-02-09
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多