如何使用dplyr lag()基于同一列中的先前行值向列添加值

时间:2017-12-08 07:21:05

标签: r dplyr

我正在尝试根据同一列的前一行和另一列中的值修改具有测试值(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变种吗?

2 个答案:

答案 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