我正在尝试根据同一列的前一行和另一列中的值修改具有测试值(1或0)的列。对于一行或两行来说这不是问题,但我需要"引导"最多50行的值,这对代码来说很麻烦。
df <- data.frame(matrix(nrow = 10, ncol = 3))
names(df) <- c("letter", "color", "test")
df[, 1] <- c("a", "a", "b", "b", "b", "b", "b", "c", "c", "c")
df[1:2, 2] <- c("blue")
df[8:10, 2] <- c("green")
df[, 3] <- c(0, 0, 1, 0, 0, 0, 0, 0, 0, 0)
DF:
letter color test
1 a blue 0
2 a blue 0
3 b <NA> 1
4 b <NA> 0
5 b <NA> 0
6 b <NA> 0
7 b <NA> 0
8 c green 0
9 c green 0
10 c green 0
我的实际数据很难为这个问题重新创建,但是这df
是我编写第一位之后的地方 - 我已经确定&#34; 1& #34;在测试列(df[3, 3]
)中我的问题开始。我现在需要&#34;领导&#34;测试栏中的1,直到&#34;颜色&#34;不是NA
和&#34;字母&#34;不是&#34; b&#34;。
以下代码是不够的(即使我的示例看起来像它一样):
... mutate(test = ifelse(letter == "b" & is.na(color), 1, test)
出于我的目的,我需要使用以下代码来引导&#34; 1:
df <- df %>%
mutate(test = ifelse(lag(test) == 1 & is.na(color), 1, test))
但是,运行此代码只会填充下一行:
letter color test
1 a blue 0
2 a blue 0
3 b <NA> 1
4 b <NA> 1
5 b <NA> 0
6 b <NA> 0
7 b <NA> 0
8 c green 0
9 c green 0
10 c green 0
为了实现这一点,我已经编写了相同的mutate
命令,如50次(在同一列上运行)。例如:
df <- df %>%
mutate(test = ifelse(lag(test) == 1 & is.na(color), 1, test),
test = ifelse(lag(test) == 1 & is.na(color), 1, test),
test = ifelse(lag(test) == 1 & is.na(color), 1, test),
test = ifelse(lag(test) == 1 & is.na(color), 1, test),
test = ifelse(lag(test) == 1 & is.na(color), 1, test))
这将返回所需的结果:
letter color test
1 a blue 0
2 a blue 0
3 b <NA> 1
4 b <NA> 1
5 b <NA> 1
6 b <NA> 1
7 b <NA> 1
8 c green 0
9 c green 0
10 c green 0
但这非常笨拙,可能会让我没有写出足够多的重复mutate
命令。
有没有办法使用dplyr
(或其他方法)来实现这一目标? for循环可能会完成工作,但我不确定它是否必要。另外,我还在学习R并且还没能真正找出apply
函数族。在这种情况下可以使用apply
变种吗?
答案 0 :(得分:1)
如果我理解正确,那么考虑你的例子,你可以使用
来达到最终结果library(dplyr)
df %>% group_by(letter, color) %>%
mutate(test = first(test))
#sample data
> dput(df)
structure(list(letter = structure(c(1L, 1L, 2L, 2L, 2L, 2L, 2L,
3L, 3L, 3L), .Label = c("a", "b", "c"), class = "factor"), color = structure(c(2L,
2L, 1L, 1L, 1L, 1L, 1L, 3L, 3L, 3L), .Label = c("<NA>", "blue",
"green"), class = "factor"), test = c(0L, 0L, 1L, 0L, 0L, 0L,
0L, 0L, 0L, 0L)), .Names = c("letter", "color", "test"), class = "data.frame", row.names = c("1",
"2", "3", "4", "5", "6", "7", "8", "9", "10"))
答案 1 :(得分:1)
您可能会因lag
而使所有内容复杂化。似乎通过letter
进行分组,您可以简单地fill
所有其他位置(1之后),其颜色为NA
。
library(tidyverse)
df %>%
group_by(letter) %>%
mutate(test = replace(test, is.na(color) & test != 1, NA)) %>%
fill(test)
给出,
# A tibble: 10 x 3 # Groups: letter [3] letter color test <chr> <chr> <dbl> 1 a blue 0 2 a blue 0 3 b <NA> 1 4 b <NA> 1 5 b <NA> 1 6 b <NA> 1 7 b <NA> 1 8 c green 0 9 c green 0 10 c green 0