我如何 select 行索引通过跳过 n 行来迭代 dplyr 中的变异?
How do I select row index to iterate over with mutate in dplyr by skipping n-rows?
我在使用 dplyrs mutate 循环时遇到问题。基本上,我想要做的就是用 B 列的第一行填充变异列的第一行,然后从第二行开始保留变异值。
- 组数据
- 改变每个组中的出现次数并过滤 n > 1
- 通过用 B 列的第一行填充第一行并用变异值填充第 2 行及以后的行来改变新列
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_col2
是 new_col
向下递减,其第一行(分组)被 column_B
的第一个值替换。条件 row_number()==1
检查这是每个组的第一行,但您可能希望将其替换为 is.na(lag(new_col))
.
请记住,只有在您 100% 确定数据集的顺序时,使用 lead()
和 lag()
才有意义。我强烈建议事先使用 arrange()
。
此外,请注意,您可以在 filter()
中使用 n()
,而不必使用 mutate()
。
我在使用 dplyrs mutate 循环时遇到问题。基本上,我想要做的就是用 B 列的第一行填充变异列的第一行,然后从第二行开始保留变异值。
- 组数据
- 改变每个组中的出现次数并过滤 n > 1
- 通过用 B 列的第一行填充第一行并用变异值填充第 2 行及以后的行来改变新列
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_col2
是 new_col
向下递减,其第一行(分组)被 column_B
的第一个值替换。条件 row_number()==1
检查这是每个组的第一行,但您可能希望将其替换为 is.na(lag(new_col))
.
请记住,只有在您 100% 确定数据集的顺序时,使用 lead()
和 lag()
才有意义。我强烈建议事先使用 arrange()
。
此外,请注意,您可以在 filter()
中使用 n()
,而不必使用 mutate()
。