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

时间:2016-11-24 04:41:29

标签: r dataframe dplyr apply

我有以下功能为一列中的变量构建一个库存效果。该变量在B列中创建一个值,该值采用ColumnA中的值,并在B列中的先前观察中添加一个结转(例如0.5)。

constructZ <- function(lag, N) {
  r <- lag^(seq_len(N)-1)
  m <- matrix(rep(r,N),nrow=N)
  z <- matrix(0,nrow=N,ncol=N)
  z[lower.tri(z,diag=TRUE)] <- m[row(m) <= (N+1-col(m))]
  z
}

我现在的问题是,我有一个面板数据集,在一个列中有许多不同情况的观察结果。每个案例都有一个特定的指标(数字)。数据如下:

ColumnA      Indicator         Time
1            1                 1
0            1                 2
0            1                 3
4            2                 1
5            2                 2
0            2                 3
4            3                 1
0            3                 2
2            3                 3

我现在希望将函数应用于所有观察的每个案例(指标)(时间)。

知道怎么做到这一点?输出应该如下:

ColumnA      Indicator         Time          ColumnB
    1            1                 1         1
    0            1                 2         0.5
    0            1                 3         0.25
    4            2                 1         4
    5            2                 2         7
    0            2                 3         3.5
    4            3                 1         4
    0            3                 2         2
    2            3                 3         3

非常感谢任何帮助或支持!

非常感谢提前!

2 个答案:

答案 0 :(得分:0)

这是我的代码。

library(dplyr) # Optional, but makes code cleaner
raw = data.frame(ColumnA =
                   c(1, 0, 0, 4, 5, 0, 4, 0, 2),
                 Indicator =
                   rep(x = 1:3, each = 3),
                 Time = 1:3)
factor = 0.5
loop = function(vec) {
  length = length(x = vec)
  if (length == 1) {
    return(vec)
  }
  if (length == 2) {
    return(vec + c(0, vec[2] * factor))
  }
  for (idx in 2:length) {
    vec[idx] = vec[idx] + vec[idx - 1] * factor
  }
  return(vec)
}
output = raw %>%
  mutate(ColumnB = 
           tapply(X = ColumnA,
                  INDEX = Indicator,
                  FUN = loop) %>%
  unlist())
output

答案 1 :(得分:0)

这是一种替代的无循环/功能编程解决方案。我们将使用Reduce()函数,该函数对向量中的每对项应用二元函数。

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

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()。)

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

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并将此滚动功能应用于每个指标组。

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