我如何 select 行索引通过跳过 n 行来迭代 dplyr 中的变异?

How do I select row index to iterate over with mutate in dplyr by skipping n-rows?

我在使用 dplyrs mutate 循环时遇到问题。基本上,我想要做的就是用 B 列的第一行填充变异列的第一行,然后从第二行开始保留变异值。

   Itemnumber column_A column_B column_C column_D column_E
   <chr>         <dbl>    <dbl>    <dbl>    <dbl>    <dbl>
 1 80126         106.      6           0     5         0  
 2 80380         131       8.38        0     0.45      2.5
 3 80676          95.4  -246           0    40         0  
 4 80142         138.    -41           0    14        10  
 5 80824         128.      3           0     1         0  
 6 80045         124.     22           0     0        70  
 7 81532         147.      5           0     7         5  
 8 80610         109.      4.71        0     0        11  
 9 82720         107.     39.7         0     0        10  
10 82623         112.     51           0     0        14 

如果我对一个组进行子集化并在基本的 for 循环中执行,则可以完成此操作。但是我不知道每个组怎么做,也按照我上面的要求。

下面的代码是我到目前为止所做的,但它没有用 column_B 的第一行填充 new_col 的第一行,也没有用 column_B 的第一行填充它第二行开始。

require(dplyr)

df %>% group_by(Itemnumber) %>% mutate(n = n()) %>% filter(n > 1) %>%
  mutate(new_col = column_B + lead(column_A, n=1L) - (lead(column_D, n=1L) - lead(column_E, n=1L)))

如果我们看一个组,它应该将值 23 放在第二行 new_col 的第一行,而第一行应该用值 6 从 column_B 到避免在最后一行使用 NA。本质上,它应该向下移动 1 行。

  Itemnumber column_A column_B column_C column_D column_E     n new_col
   <chr>         <dbl>    <dbl>    <dbl>    <dbl>    <dbl> <int>   <dbl>
 1 80126          96.3        6        0        5        0    15      23
 2 80126         123.        17        0        3       20    15      26
 3 80126          96.7       24        0        1       10    15      18
 4 80126         129.        10        0        6        0    15      20
 5 80126         117.        18        0        0       10    15      16
 6 80126         112.        12        0        2        0    15      22
 7 80126         106.        13        0        0       10    15      23
 8 80126         108.        21        0        0       10    15      29
 9 80126         124.        28        0        2       10    15      37
10 80126          99.9       24        0       11       20    15      22
11 80126         127.        10        0        2        0    15      18
12 80126         111.         9        0        2       10    15      19
13 80126         115.        10        0        0       10    15      19
14 80126         124.        17        0        1       10    15      37
15 80126         111.        29        0        0       20    15      NA
   

下面是我想用 new_col 做的事情(我知道这行不通)=(


df %>% group_by(Itemnumber) %>% 
  mutate(n = n()) %>% filter(n > 1) %>%
  mutate(new_col[i+1] = column_B + lead(column_A, n=1L) - (lead(column_D, n=1L) - lead(column_E, n=1L))) %>% 
  fill(ifelse(is.na(new_col[1]), 
              column_B[1], 
              fill(new_col, .direction="downup"))
       )

感谢所有能得到的帮助!

编辑:

从数据集中添加三组(Itemnumber 列)的样本 dput()。

structure(list(Itemnumber = c("80126", "81532", "82181", "80126", 
"80126", "82181", "81532", "80126", "82181", "80126", "81532", 
"81532", "82181", "80126", "81532", "81532", "81532", "82181", 
"80126", "81532", "81532", "80126", "82181", "80126", "82181", 
"82181", "82181", "80126", "82181", "80126", "80126", "82181", 
"80126", "82181", "80126", "82181", "82181", "81532", "80126"
), column_A = c(96.3, 107.1, 122.8, 122.9, 96.7, 117.1, 88, 129.3, 
115, 117.2, 123.5, 99.5, 120.6, 111.9, 117.5, 135.5, 132.6, 120.4, 
105.6, 127.7, 133.1, 107.8, 119.1, 124.5, 129.7, 110.2, 92.8, 
99.9, 71.6, 126.7, 110.8, 110.1, 114.9, 124.8, 124.4, 115.7, 
108.1, 89.3, 110.8), column_B = c(6, 5, 49, 17, 24, 36, 4, 10, 
44, 18, 10, 10, 29, 12, 10, 12, 8, 29, 13, 12, 13, 21, 156, 28, 
263, 240, 200, 24, 129, 10, 9, 47, 10, 65, 17, 69, 79, 18, 29
), column_C = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0), column_D = c(5, 7, 0, 3, 1, 8, 0, 6, 0, 0, 1, 0, 0, 
2, 1, 0, 2, 0, 0, 0, 0, 0, 2, 2, 0, 17, 20, 11, 52, 2, 2, 126, 
0, 0, 1, 0, 0, 0, 0), column_E = c(0, 5, 14, 20, 10, 14, 5, 0, 
14, 10, 5, 0, 14, 0, 0, 5, 0, 14, 10, 5, 5, 10, 140, 10, 126, 
0, 0, 20, 0, 0, 10, 84, 10, 42, 10, 14, 14, 5, 20)), row.names = c(NA, 
-39L), class = c("tbl_df", "tbl", "data.frame"))

预期的输出应该是这样的

   Itemnumber column_A column_B column_C column_D column_E     n new_col
   <chr>         <dbl>    <dbl>    <dbl>    <dbl>    <dbl> <int>   <dbl>
 1 80126          96.3        6        0        5        0    15       6
 2 80126         123.        17        0        3       20    15      23
 3 80126          96.7       24        0        1       10    15      26
 4 80126         129.        10        0        6        0    15      18
 5 80126         117.        18        0        0       10    15      20
 6 80126         112.        12        0        2        0    15      16
 7 80126         106.        13        0        0       10    15      22
 8 80126         108.        21        0        0       10    15      23
 9 80126         124.        28        0        2       10    15      29
10 80126          99.9       24        0       11       20    15      37
11 80126         127.        10        0        2        0    15      22
12 80126         111.         9        0        2       10    15      18
13 80126         115.        10        0        0       10    15      19
14 80126         124.        17        0        1       10    15      19
15 80126         111.        29        0        0       20    15      37

如果没有正确的预期输出就很难回答(尤其是当您使用 80126 的示例与您的 dput() 数据集不匹配时),但这里是一个基于我从文本中理解的内容的答案:

df %>% 
  group_by(Itemnumber) %>% 
  filter(n() > 1) %>%
  mutate(new_col = column_B + lead(column_A, n=1L) - (lead(column_D, n=1L) - lead(column_E, n=1L))) %>%
  mutate(new_col2 = ifelse(row_number()==1, column_B, lag(new_col))) %>% 
  ungroup() %>% 
  arrange(Itemnumber)

  # # A tibble: 39 x 8
  # Itemnumber column_A column_B column_C column_D column_E new_col new_col2
  # <chr>         <dbl>    <dbl>    <dbl>    <dbl>    <dbl>   <dbl>    <dbl>
  # 1 80126          96.3        6        0        5        0    146.       6
  # 2 80126         123.        17        0        3       20    123.     146.
  # 3 80126          96.7       24        0        1       10    147.     123.
  # 4 80126         129.        10        0        6        0    137.     147.
  # 5 80126         117.        18        0        0       10    128.     137.
  # 6 80126         112.        12        0        2        0    128.     128.
  # 7 80126         106.        13        0        0       10    131.     128.
  # 8 80126         108.        21        0        0       10    154.     131.
  # 9 80126         124.        28        0        2       10    137.     154.
  #10 80126          99.9       24        0       11       20    149.     137.

new_col2new_col 向下递减,其第一行(分组)被 column_B 的第一个值替换。条件 row_number()==1 检查这是每个组的第一行,但您可能希望将其替换为 is.na(lag(new_col)) .

请记住,只有在您 100% 确定数据集的顺序时,使用 lead()lag() 才有意义。我强烈建议事先使用 arrange()

此外,请注意,您可以在 filter() 中使用 n(),而不必使用 mutate()