【问题标题】:Perform arithmetic on each element of a vector (column) based on the previous vector element over multiple vectors (columns) in a data frame根据数据帧中多个向量(列)上的前一个向量元素对向量(列)的每个元素执行算术运算
【发布时间】:2018-02-12 19:01:09
【问题描述】:

我有一个包含 12 列的数据框,我需要对其中的 7 列执行一些基本算术运算:列 5:12。下面粘贴了名为 test 的数据框。

我希望执行的算术将根据前一个元素更改每个元素,但每列中的第一个元素除外,因为每列第一个元素的算术与后续元素不同。此外,由于涉及其原始值,因此等式会更改元素向量。我对前一行代码中的第一个元素进行了算术运算,所以这已经是正确的值了。

这是数学:

B = (1-.08)Bt + .08(z)

其中 Bt 是前一个元素的值,z 是当前元素的值。然后每个元素都会变成 B。

编辑:我可能不清楚,但 Bt 将是从前一个元素中新计算的 B 值。所以这是一步一步的进步。

我一直在用 apply 尝试这个,但我很困惑,因为我过去只使用 for 循环对单个向量做过类似的事情,但在这种情况下,我基于之前创建了全新的向量元素元素,就像这个例子一样,第一个元素是预定义的。

我可以对此进行概念化,但无法用我目前在 R 中的技能对其进行编码。

非常感谢任何帮助。谢谢。

数据:

 test <- 

 structure(list(Forecast_day = c(8, 8, 8, 8, 8, 8), Forecast_date = structure(c(17555, 
    17556, 17557, 17558, 17559, 17560), class = "Date"), DeliveryDate = structure(c(17563, 
    17564, 17565, 17566, 17567, 17568), class = "Date"), HourEnding = c(1L, 
    1L, 1L, 1L, 1L, 1L), Coast = c(-0.0459999999999999, -11.6, -3.8, 
    -7.09999999999999, -9.6, -11.2), East = c(0.01, -8.5, -1.5, -3.5, 
    -0.5, -9.5), FarWest = c(-0.07, -6.5, -9, -11.5, 6, -10.5), North = c(0.01, 
    -2.5, -1.5, -1.5, 14, 0), NorthCentral = c(-0.07, -7.25, -5.75, 
    -10.75, 6.75, 1.5), SouthCentral = c(-0.01, -10, -8.5, -3.5, 
    -8.5, -11), Southern = c(-0.04, -10.8, -4.6, -7.8, -9.6, -12), 
        West = c(-0.16, -7.4, -6.6, -13.2, 7.8, -9)), .Names = c("Forecast_day", 
    "Forecast_date", "DeliveryDate", "HourEnding", "Coast", "East", 
    "FarWest", "North", "NorthCentral", "SouthCentral", "Southern", 
    "West"), row.names = c(NA, -6L), class = "data.frame")

【问题讨论】:

  • 这样的东西有用吗? dplyr::mutate_at(test, 5:12, funs((1-.08) * dplyr::lag(.) + .08 * .))
  • 不幸的是,它没有。我在第 5:12 列的第一行中得到 NA,随后的值不正确。
  • 有没有办法在每列的第二个元素开始这段代码?那应该可以。
  • 由于第一行已经正确,您可以随时重新替换该行。前任。执行r1 &lt;- test[1, ] 然后运行上面的mutate_at 调用,然后执行test[1, ] &lt;- r1
  • 或者一步一步作为test %&gt;% mutate_at(5:12, funs((1 - .08)*lag(., default = .[1]) + 0.08*. ))

标签: r


【解决方案1】:

您可以使用Reduce 元函数沿向量顺序应用算术,使用先前的结果作为输入之一。

首先,将算术封装在一个函数中。

update_with_previous <- function(previous, current) {
  (1 - 0.08) * previous + 0.08 * current
}

要为一列执行此操作,请使用Reduce 中的函数并设置accumulate = TRUE 以保留每个结果。

Reduce(update_with_previous, test$Coast, accumulate = TRUE)
# [1] -0.046000 -0.970320 -1.196694 -1.668959 -2.303442 -3.015167

使用lapply同时替换多列。

test[5:12] <- lapply(
  X          = test[5:12],
  FUN        = Reduce,
  f          = update_with_previous,
  accumulate = TRUE
)

【讨论】:

  • 效果很好!我不知道Reduce。看起来我迟早会完全从 Excel 迁移出来。非常感谢。
【解决方案2】:

可能会有更优雅的东西,但我认为这会起作用:

B <- function(Bt,z) (1-.08)*Bt + .08*(z)
tmp <- sapply(test[,5:12] ,function(g) sapply(2:nrow(test),function(x) B(Bt = g[x-1],z = g[x])))
test[2:nrow(test),5:12] <-  tmp

【讨论】:

  • 这绝对有效,但仍不能计算正确的值。如果我不清楚,我深表歉意,但我希望将以下元素计算中每个元素的新计算值 B 用作 Bt。虽然,您的 g[x-1] 应该涵盖这一点....不知道为什么它不起作用。
猜你喜欢
  • 2021-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-19
  • 2021-07-28
  • 2018-10-16
  • 1970-01-01
相关资源
最近更新 更多