有没有一种方法可以在不使用 for 循环的情况下重复求解从数据框创建的矩阵?

Is there a way to repeatedly solve matrices created from a data frame without using for loops?

更新

我一直在尝试 apply() 函数,但输出让我很困惑。我需要 data.framedata.tableapply(smallExample, 1, SectionDev) 给出了正确的输出,但在列表中。我读过 sapply() 可以输出 data.framematrix 但我无法将整行输入函数。

新函数

  SectionDev <- function(x){
    parameters <- data.table("Name" = c("Head", "Foot", "Pillow", "Mattress", "Sleeping", "Restless"),
                             "Space" = c(8, 78, 17, 17, 3, 8), 
                             "Portion" = c(2, 4, 2, 2, 3, 3))

    RG <- as.numeric(x[which(names(x) == "Gas")])
    RS <- as.numeric(x[which(names(x) == "Solid")])

    A <- data.frame(MG=c(1, 0, 1, 0),
                    MS=c(1, 0, 0, 1),
                    VG=c(0, 1, -1*RG, 0),
                    VS=c(0, 1, 0, -1*RS))

    for (j in 1:nrow(parameters)) {
      SectName <- as.vector(as.matrix(parameters[j, `Name`]))
      Ac <- parameters[j, `Portion`]
      Vt <- parameters[j, `Space`]

      Pushing <- as.numeric(x[which(names(x) == SectName)])
      Driving <- as.numeric(Pushing * 249.1)
      Pressing <- Driving*Ac / 9.8
      b <- c(Pressing, Vt, 0, 0)

      MatrixConstants <- data.table("Timestamp" = as.vector(as.matrix(x[which(names(x) == "Timestamp")])),
                                    "Section" = SectName,
                                    RG,
                                    RS) 

      MatrixSolution <- solve(A,b)

      MatrixPtResult <- cbind(MatrixConstants,t(
        as.data.frame(MatrixSolution)))

      if (exists("MatrixTest")){
        rlist <- list(MatrixTest, MatrixPtResult)
      } else {
        rlist <- list(MatrixPtResult)
      }

      MatrixTest <- rbindlist(rlist)
      }

    return(MatrixTest)
  }

期望输出

> MatrixOutput[1:12,]
              Timestamp  Portion Gas Solid        MG         MS         VG
 1: 2019-04-24 06:00:00     Head  18   234  149.2218  -67.88299   8.290098
 2: 2019-04-24 06:00:00     Foot  18   234 1427.7993 -309.39116  79.322184
 3: 2019-04-24 06:00:00   Pillow  18   234  318.7908 -166.28061  17.710601
 4: 2019-04-24 06:00:00 Mattress  18   234  183.2262 1596.05952  10.179233
 5: 2019-04-24 06:00:00 Sleeping  18   234 -316.4209 4815.47194 -17.578940
 6: 2019-04-24 06:00:00 Restless  18   234 -549.3597 9013.67602 -30.519983
 7: 2019-04-24 07:00:00     Head  17   239  141.7429  -80.73885   8.337819
 8: 2019-04-24 07:00:00     Foot  17   239 1365.2541 -551.86634  80.309064
 9: 2019-04-24 07:00:00   Pillow  17   239  303.3448 -201.67136  17.843813
10: 2019-04-24 07:00:00 Mattress  17   239  178.7719 1549.67705  10.515996
11: 2019-04-24 07:00:00 Sleeping  17   239 -277.9378 4624.47863 -16.349283
12: 2019-04-24 07:00:00 Restless  17   239 -501.7540 8966.07028 -29.514938
            VS
 1: -0.2900983
 2: -1.3221844
 3: -0.7106009
 4:  6.8207672
 5: 20.5789399
 6: 38.5199830
 7: -0.3378195
 8: -2.3090642
 9: -0.8438132
10:  6.4840044
11: 19.3492830
12: 37.5149384

原创

我必须为数据中的每个时间点和位置求解相同的矩阵。 for 循环有效,但在 12,000 多个时间点和 6 个位置时速度不快。

有没有办法不使用 for 来做到这一点?它只是感觉不像我现在做的那样。

我确实尝试过将 foreachdoParallel 一起使用,但实际上它比用 TERR 编写的 for 慢。

有两个嵌套循环。第一个提取时间点的测量值,第二个为每个位置执行 solve

  for (i in 1:nrow(smallExample)) {
      RG <- as.matrix(smallExample[i, "Gas"])
      RS <- as.matrix(smallExample[i, "Solid"])

      A <- data.frame(MG=c(1, 0, 1, 0),
                      MS=c(1, 0, 0, 1),
                      VG=c(0, 1, -1*RG,0),
                      VS=c(0, 1, 0, -1*RS))

      for (j in 1:nrow(parameters)) {
        SectName <- as.vector(as.matrix(parameters[j, "Name"]))
        Ac <- parameters[j, "Portion"]
        Vt <- parameters[j, "Space"]

        Pushing <- smallExample[i, get(SectName)]
        Driving <- as.matrix(Pushing*249.1) 
        Pressing <- Driving * as.matrix(Ac) / 9.8
        b <- c(Pressing,Vt,0,0)

        MatrixConstants <- data.table("Timestamp" = as.vector(as.matrix(smallExample[i, "Timestamp"])),
                                      "Portion" = SectName,
                                      RG,
                                      RS)

        MatrixSolution <- solve(A,b)

        MatrixPtResult <- cbind(MatrixConstants,t(
          as.data.frame(MatrixSolution)))

        if (exists("MatrixOutput")){
          rlist <- list(MatrixOutput, MatrixPtResult)
        } else {
          rlist <- list(MatrixPtResult)
        }

        MatrixOutput <- rbindlist(rlist)
        cat(paste("\r",i, "Observations of ", nrow(smallExample),"\t",nrow(MatrixOutput),"Matrix results",sep = " "))
      }
  }

结果是时间、位置、测量值和解决方案的四个部分的非透视 table。

数据:

library(data.table)

smallExample <- structure(list(Gas = c(18,  17, 15,  14,  12,  11), 
                                 Solid = c(234, 239,  237, 238,  233, 239),
                                 Timestamp = structure(c(1556085600,
                                                         1556089200, 
                                                         1556092800, 
                                                         1556096400, 
                                                         1556100000, 
                                                         1556103600),
                                                       class = c("POSIXct", "POSIXt"), tzone = "UTC"), 
                                 Head = c(1.6, 1.2, 1.1, 1.0, 0.8, 0.7), 
                                 Foot = c(11, 8, 7, 6, 5, 4), 
                                 Pillow = c(3, 2, 2, 2, 1, 1), 
                                 Mattress = c(35, 34, 31, 30, 28, 26), 
                                 Sleeping = c(59, 57, 59, 58, 59, 59), 
                                 Restless = c(111, 111, 110, 111, 112, 113)),
                            class = c("data.table", "data.frame"),
                            row.names = c(NA_integer_, -6L))

parameters <- data.table("Name" = c("Head", "Foot", "Pillow", "Mattress", "Sleeping", "Restless"),
                         "Space" = c(8, 78, 17, 17, 3, 8), 
                         "Portion" = c(2, 4, 2, 2, 3, 3))

解决方案是将 applydo.callrbind 一起使用(thanks to fotNelton). Benchmarking with microbenchmark using apply came in 60% faster. Just left wishing I could get do.call(rbindlist,))

MatrixAnswer <- as.data.table(do.call(rbind, apply(MatrixSubTest, 1, SectionMasses)))