滚动百分比沿列添加
Rolling percentage add along column
我觉得这在 base R 中应该很容易,但我就是想不通。
我有一个简单的数据框,假设它看起来像这样
tbl <- read.table(text =
"Field1 Field2
100 200
150 180
200 160
280 250
300 300
300 250",
header = TRUE)
现在,我想要做的是创建一个将应用滚动百分比加法的函数,例如:
fn <- function(tbl, pct) {}
接受上面的数据帧 tbl
。它根据 pct
将当前行的百分比部分添加到下一行,并几乎以累积方式滚动。
例如,fn(tbl$Field1, 0.1)
将生成以下结果:
100 (100 + 0.1*0)
160 (150 + 0.1*100 = 160)
216 (200 + 0.1*160 = 216)
301.6 (280 + 0.1*216 = 301.6)
等等
我会使用包解决方案,但更喜欢基础 R,因为它有助于学习过程!我的长期目标是通过 field 和 pct 的每个组合构建一个循环的过程,这样我就可以在回归模型中测试它的效果;因此我的直觉是我以后可以应用的功能是前进的方向。
谢谢。
如果您想仅使用基础 R 编写解决方案并使用 for
循环和索引从基础学习编程,您可能只知道可以编写一个函数,其语料库如下所示:
solution= tbl$Field1
for (i in 1:length(tbl$Field1)) {
if (i==1) {
solution[1] = tbl$Field1[1]
} else {
solution[i] = tbl$Field1[i] + pct * solution[i-1]
}
}
尽管我建议您查看更高级的解决方案。已经提到的 lag
功能可以派上用场。
您可以使用 Reduce()
函数,如下所示。
cumpersum = function(x, percent = 0.1) {
Reduce(function(x1, x2) percent * x1 + x2, x, accumulate = TRUE)
}
dat <- data.frame(
Field1 = c(100, 150, 200, 280, 300, 300),
Field2 = c(200, 180, 160, 250, 300, 250)
)
dat$Field1cumper <- cumpersum(dat$Field1, .1)
dat
# Field1 Field2 Field1cumper
# 1 100 200 100.0
# 2 150 180 160.0
# 3 200 160 216.0
# 4 280 250 301.6
# 5 300 300 330.2
# 6 300 250 333.0
很想找出一种不涉及显式循环的解决方案,但我想不出一个。您可以将所需结果分解为乘以 pct^c(0, 1, 2, ...)
的数字总和,但我认为这只会让您进行大量额外计算。所以我的解决方案很简单:
fn = function(x, pct) {
n = length(x)
result = NA*x
last_result = 0
for(i in 1:n) {
result[i] = last_result = x[i] + last_result*pct
}
return(result)
}
fn(tbl$Field1, 0.1)
# [1] 100.000 160.000 216.000 301.600 330.160 333.016
filter()
function 是 stats
包的一部分,它是基于 R 的。保持小数点后一位:
round(filter(tbl$Field1, 0.1, method="recursive"), 1)
这将产生以下结果
100.0 160.0 216.0 301.6 330.2 333.0
我觉得这在 base R 中应该很容易,但我就是想不通。 我有一个简单的数据框,假设它看起来像这样
tbl <- read.table(text =
"Field1 Field2
100 200
150 180
200 160
280 250
300 300
300 250",
header = TRUE)
现在,我想要做的是创建一个将应用滚动百分比加法的函数,例如:
fn <- function(tbl, pct) {}
接受上面的数据帧 tbl
。它根据 pct
将当前行的百分比部分添加到下一行,并几乎以累积方式滚动。
例如,fn(tbl$Field1, 0.1)
将生成以下结果:
100 (100 + 0.1*0)
160 (150 + 0.1*100 = 160)
216 (200 + 0.1*160 = 216)
301.6 (280 + 0.1*216 = 301.6)
等等
我会使用包解决方案,但更喜欢基础 R,因为它有助于学习过程!我的长期目标是通过 field 和 pct 的每个组合构建一个循环的过程,这样我就可以在回归模型中测试它的效果;因此我的直觉是我以后可以应用的功能是前进的方向。
谢谢。
如果您想仅使用基础 R 编写解决方案并使用 for
循环和索引从基础学习编程,您可能只知道可以编写一个函数,其语料库如下所示:
solution= tbl$Field1
for (i in 1:length(tbl$Field1)) {
if (i==1) {
solution[1] = tbl$Field1[1]
} else {
solution[i] = tbl$Field1[i] + pct * solution[i-1]
}
}
尽管我建议您查看更高级的解决方案。已经提到的 lag
功能可以派上用场。
您可以使用 Reduce()
函数,如下所示。
cumpersum = function(x, percent = 0.1) {
Reduce(function(x1, x2) percent * x1 + x2, x, accumulate = TRUE)
}
dat <- data.frame(
Field1 = c(100, 150, 200, 280, 300, 300),
Field2 = c(200, 180, 160, 250, 300, 250)
)
dat$Field1cumper <- cumpersum(dat$Field1, .1)
dat
# Field1 Field2 Field1cumper
# 1 100 200 100.0
# 2 150 180 160.0
# 3 200 160 216.0
# 4 280 250 301.6
# 5 300 300 330.2
# 6 300 250 333.0
很想找出一种不涉及显式循环的解决方案,但我想不出一个。您可以将所需结果分解为乘以 pct^c(0, 1, 2, ...)
的数字总和,但我认为这只会让您进行大量额外计算。所以我的解决方案很简单:
fn = function(x, pct) {
n = length(x)
result = NA*x
last_result = 0
for(i in 1:n) {
result[i] = last_result = x[i] + last_result*pct
}
return(result)
}
fn(tbl$Field1, 0.1)
# [1] 100.000 160.000 216.000 301.600 330.160 333.016
filter()
function 是 stats
包的一部分,它是基于 R 的。保持小数点后一位:
round(filter(tbl$Field1, 0.1, method="recursive"), 1)
这将产生以下结果
100.0 160.0 216.0 301.6 330.2 333.0