减去上面不是 NA 的数字

Subtract above number that is not NA

我有一个 table 类似于这个没有差异列的最小示例:

trigger values difference
0 3
0 NA
0 NA
1 5 2
0 4
0 NA
1 10 6

我想从每个触发点(trigger = 1)的数字中减去上述数字(并省略 NA)

有没有办法在 R 中做到这一点?

编辑:

我现在遇到的情况是触发器靠得很近,就像这个例子一样:

trigger values difference
0 3
0 NA
0 NA
1 5 2
0 4
1 5 1
0 10

我该如何解决这个问题?

在'trigger'上创建一个cumsum的分组列,取lag,然后将第一个和最后一个元素与replace相差作为last 每组价值

library(dplyr)
df1 %>%
    group_by(grp = lag(cumsum(trigger), default = 0)) %>% 
    mutate(difference = replace(rep(NA, n()), n(),
         values[n()] - values[1])) %>%
    ungroup %>%
    select(-grp)

-输出

# A tibble: 7 × 3
  trigger values difference
    <int>  <int>      <int>
1       0      3         NA
2       0     NA         NA
3       0     NA         NA
4       1      5          2
5       0      4         NA
6       0     NA         NA
7       1     10          6

对于第二种情况,我们可能需要一个条件if/else来检查行数即if行数大于1只需要计算到replace

df2 %>%  
  group_by(grp = lag(cumsum(trigger), default = 0)) %>% 
  mutate(difference = if(n() > 1) replace(rep(NA, n()), n(), 
         values[n()] - values[1]) else NA) %>%
  ungroup

-输出

# A tibble: 7 × 4
  trigger values   grp difference
    <int>  <int> <dbl>      <int>
1       0      3     0         NA
2       0     NA     0         NA
3       0     NA     0         NA
4       1      5     0          2
5       0      4     1         NA
6       1      5     1          1
7       0     10     2         NA

数据

df1 <- structure(list(trigger = c(0L, 0L, 0L, 1L, 0L, 0L, 1L), values = c(3L, 
NA, NA, 5L, 4L, NA, 10L)), class = "data.frame", row.names = c(NA, 
-7L))

df2 <- structure(list(trigger = c(0L, 0L, 0L, 1L, 0L, 1L, 0L), values = c(3L, 
NA, NA, 5L, 4L, 5L, 10L)), class = "data.frame", row.names = c(NA, 
-7L))
# Import data: df => data.frame
df <- structure(list(trigger = c(0L, 0L, 0L, 1L, 0L, 0L, 1L), values = c(3L, 
NA, NA, 5L, 4L, NA, 10L), diff_col = c(NA, NA, NA, 2L, -1L, NA, 
6L)), row.names = c(NA, -7L), class = "data.frame")

# Create an empty vector: diff_col => integer vector
df$diff_col <- NA_integer_

# Difference the X.values vector, ignoring NAs: 
# diff_col => integer vector
df[which(!(is.na(df$values)))[-1], "diff_col"] <- diff(
   na.omit(
      df$values
   )
)

# Nullify the value if the trigger is 0:
# diff_col => integer vector
df$diff_col <- with(
   df, 
   ifelse(
      trigger == 0,
      NA_integer_,
      diff_col
   )
)