且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

根据其他列中的值将 R 函数应用于行

更新时间:2023-12-01 15:22:34

这里是另一种无循环/函数式编程解决方案.我们将使用 Reduce() 函数,该函数对向量中的每对项目应用二元函数.

Here is an alternative loop-free/functional programming solution. We are going to use the Reduce() function which applies a binary function over every pair of items in a vector.

例如,Reduce(`+`, xs) 计算向量中值的总和.如果我们设置 accumulate = TRUE,我们会得到一个滚动/累积和.

For example, Reduce(`+`, xs) computes the sum of values in vector. If we set accumulate = TRUE, we get a rolling/cumulative sum.

Reduce(`+`, 1:6)
#> [1] 21

# What Reduce is doing here, basically
((((((1) + 2) + 3) + 4) + 5) + 6)
#> [1] 21

# Keep each intermediate sum
Reduce(`+`, 1:6, accumulate = TRUE)
#> [1]  1  3  6 10 15 21

(purrr 包将这两种行为分为不同的函数:reduce()accumulate().)

(The purrr package separates these two behaviors into different functions: reduce() and accumulate().)

我们可以使用 Reduce() 来实现结转/缩放功能.首先,定义一个处理一对值的函数,然后使用 Reduce() 来执行它的滚动版本.

We can use Reduce() to implement the carry-over/scaling function. First, define a function that works on a pair of values, then use Reduce() to perform a rolling version of it.

rolling_scale <- function(xs, scale_factor) {
  scale_pair <- function(x1, x2) x2 + scale_factor * x1
  Reduce(scale_pair, xs, accumulate = TRUE)
}

rolling_scale(c(4, 5, 0), .5)
#> [1] 4.0 7.0 3.5

现在,我们可以使用 dplyr 并将此滚动功能应用于每个指标组.

Now, we can use dplyr and apply this rolling function to each indicator group.

library(dplyr)

raw <- data.frame(
  ColumnA = c(1, 0, 0, 4, 5, 0, 4, 0, 2), 
  Indicator = rep(x = 1:3, each = 3), 
  Time = 1:3)

raw %>% 
  group_by(Indicator) %>% 
  mutate(ColumnB = rolling_scale(ColumnA, .5)) %>% 
  ungroup()
#> # A tibble: 9 × 4
#>   ColumnA Indicator  Time ColumnB
#>     <dbl>     <int> <int>   <dbl>
#> 1       1         1     1    1.00
#> 2       0         1     2    0.50
#> 3       0         1     3    0.25
#> 4       4         2     1    4.00
#> 5       5         2     2    7.00
#> 6       0         2     3    3.50
#> 7       4         3     1    4.00
#> 8       0         3     2    2.00
#> 9       2         3     3    3.00