如何标记数据框组的最后一行?

How to flag the last row of a data frame group?

假设我们从下面的数据框开始 df:

 ID <- c(1, 1, 1, 5, 5)
 Period <- c(1,2,3,1,2)
 Value <- c(10,12,11,4,6)
 df <- data.frame(ID, Period, Value)

      ID Period Value
    1  1      1    10
    2  1      2    12
    3  1      3    11
    4  5      1     4
    5  5      2     6

现在,我使用 dplyr 添加了一个“计算”列,将每行的周期和值相乘,得到以下结果:

> df %>% mutate(Calculate = Period * Value)

  ID Period Value Calculate
1  1      1    10        10
2  1      2    12        24
3  1      3    11        33
4  5      1     4         4
5  5      2     6        12

我想修改上面的“计算”,在到达给定 ID 的最后一行时给我一个 0 值,这样数据框输出看起来像:

  ID Period Value Calculate
1  1      1    10        10
2  1      2    12        24
3  1      3    11         0
4  5      1     4         4
5  5      2     6         0

我打算使用 lead() 函数查看下一行以查看 ID 是否发生变化,但不确定在到达数据帧末尾时会发生这种情况。

如何使用 dplyr 完成此操作?

您可以 group_by ID 并将每个 ID 的最后一行替换为 0。

library(dplyr)

df %>% 
  mutate(Calculate = Period * Value) %>%
  group_by(ID) %>%
  mutate(Calculate = replace(Calculate, n(), 0)) %>%
  ungroup

#     ID Period Value Calculate
#  <dbl>  <dbl> <dbl>     <dbl>
#1     1      1    10        10
#2     1      2    12        24
#3     1      3    11         0
#4     5      1     4         4
#5     5      2     6         0

这应该有效。您也可以将 rownum 替换为 Period(最有可能)

ID <- c(1, 1, 1, 5, 5)
Period <- c(1,2,3,1,2)
Value <- c(10,12,11,4,6)
df <- data.frame(ID, Period, Value)

df = df %>% mutate(Calculate = Period * Value)
df$rownum = rownames(df)

df = df %>% 
  group_by(ID) %>%
  mutate(Calculate = ifelse(rownum == max(rownum), 0, Calculate)) %>%
  ungroup()

 A tibble: 5 × 5
     ID Period Value Calculate rownum
  <dbl>  <dbl> <dbl>     <dbl> <chr> 
1     1      1    10        10 1     
2     1      2    12        24 2     
3     1      3    11         0 3     
4     5      1     4         4 4     
5     5      2     6         0 5  

还有一种可能性:

library(tidyverse)

ID <- c(1, 1, 1, 5, 5)
Period <- c(1,2,3,1,2)
Value <- c(10,12,11,4,6)
df <- data.frame(ID, Period, Value)

df %>% 
  mutate(Calculate = Period * Value) %>% 
  group_by(ID) %>% 
  mutate(Calculate = if_else(row_number() == n(), 0, Calculate)) %>% 
  ungroup

#> # A tibble: 5 × 4
#>      ID Period Value Calculate
#>   <dbl>  <dbl> <dbl>     <dbl>
#> 1     1      1    10        10
#> 2     1      2    12        24
#> 3     1      3    11         0
#> 4     5      1     4         4
#> 5     5      2     6         0
ID <- c(1, 1, 1, 5, 5)
Period <- c(1,2,3,1,2)
Value <- c(10,12,11,4,6)
df <- data.frame(ID, Period, Value)

library(tidyverse)
df %>% 
  mutate(Calculate = Period * Value * duplicated(ID, fromLast = TRUE)) 
#>   ID Period Value Calculate
#> 1  1      1    10        10
#> 2  1      2    12        24
#> 3  1      3    11         0
#> 4  5      1     4         4
#> 5  5      2     6         0

reprex package (v2.0.1)

创建于 2022-01-09