首页 文章

将mutate与条件值组合使用

提问于
浏览
55

在具有四列的大型数据框(“myfile”)中,我必须添加第五列,其中值基于前四列 . 最近我成为了dplyr的忠实粉丝,主要是因为它在大型数据集中的速度 . 所以我想知道我是否可以使用mutate函数处理我的问题 .

我的数据帧(实际上是它的较短版本)看起来有点像这样:

V1 V2 V3 V4
1  1  2  3  5
2  2  4  4  1
3  1  4  1  1
4  4  5  1  3
5  5  5  5  4

第五列(V5)的值基于一些条件规则:

if (V1==1 & V2!=4){
V5 <- 1
}
else if (V2==4 & V3!=1){
V5 <- 2
}
else {
V5 <- 0
}

现在我想使用mutate函数在所有行上使用这些规则(所以我不必使用慢循环) . 像这样的东西(是的,我知道它不会这样工作!):

myfile <- mutate(myfile, if (V1==1 & V2!=4){V5 = 1}
    else if (V2==4 & V3!=1){V5 = 2}
    else {V5 = 0})

这应该是结果:

V1 V2 V3 V4 V5
1  1  2  3  5  1
2  2  4  4  1  2
3  1  4  1  1  0
4  4  5  1  3  0
5  5  5  5  4  0

如何在 dplyr 中执行此操作?

3 回答

  • 10

    试试这个:

    myfile %>% mutate(V5 = (V1 == 1 & V2 != 4) + 2 * (V2 == 4 & V3 != 1))
    

    赠送:

    V1 V2 V3 V4 V5
    1  1  2  3  5  1
    2  2  4  4  1  2
    3  1  4  1  1  0
    4  4  5  1  3  0
    5  5  5  5  4  0
    

    或这个:

    myfile %>% mutate(V5 = ifelse(V1 == 1 & V2 != 4, 1, ifelse(V2 == 4 & V3 != 1, 2, 0)))
    

    赠送:

    V1 V2 V3 V4 V5
    1  1  2  3  5  1
    2  2  4  4  1  2
    3  1  4  1  1  0
    4  4  5  1  3  0
    5  5  5  5  4  0
    

    建议您为数据框架获得更好的名称 . myfile使它看起来好像拥有一个文件名 .

    上面使用了这个输入:

    myfile <- 
    structure(list(V1 = c(1L, 2L, 1L, 4L, 5L), V2 = c(2L, 4L, 4L, 
    5L, 5L), V3 = c(3L, 4L, 1L, 1L, 5L), V4 = c(5L, 1L, 1L, 3L, 4L
    )), .Names = c("V1", "V2", "V3", "V4"), class = "data.frame", row.names = c("1", 
    "2", "3", "4", "5"))
    

    Update 1 由于最初发布的dplyr已将 %.% 更改为 %>% 所以已相应修改了答案 .

    Update 2 dplyr现在有 case_when ,它提供了另一种解决方案:

    myfile %>% 
           mutate(V5 = case_when(V1 == 1 & V2 != 4 ~ 1, 
                                 V2 == 4 & V3 != 1 ~ 2,
                                 TRUE ~ 0))
    
  • 14

    使用 dplyr 0.7.2 ,您可以使用非常有用的 case_when 函数:

    x=read.table(
     text="V1 V2 V3 V4
     1  1  2  3  5
     2  2  4  4  1
     3  1  4  1  1
     4  4  5  1  3
     5  5  5  5  4")
    x$V5 = case_when(x$V1==1 & x$V2!=4 ~ 1,
                     x$V2==4 & x$V3!=1 ~ 2,
                     TRUE ~ 0)
    

    dplyr::mutate 表示,它给出:

    x = x %>% mutate(
         V5 = case_when(
             V1==1 & V2!=4 ~ 1,
             V2==4 & V3!=1 ~ 2,
             TRUE ~ 0
         )
    )
    

    请注意 NA 未经特殊处理,因为它可能会产生误导 . 仅当没有条件匹配时,该函数才会返回 NA . 如果你在 TRUE ~ ... 中添加一行,就像我在我的例子中所做的那样,那么返回值将永远不会是 NA .

    因此,你必须通过添加类似 is.na(x$V1) | is.na(x$V3) ~ NA_integer_ 的语句,明确地告诉 case_whenNA 放在它所属的位置 . 提示: dplyr::coalesce() 函数有时候非常有用!

    而且,请注意单独 NA 通常不起作用,你必须输入特殊的 NA 值: NA_integer_NA_character_NA_real_ .

  • 63

    看起来 mosaic 包中的 derivedFactor 就是为此而设计的 . 在这个例子中,它看起来像:

    library(mosaic)
    myfile <- mutate(myfile, V5 = derivedFactor(
        "1" = (V1==1 & V2!=4),
        "2" = (V2==4 & V3!=1),
        .method = "first",
        .default = 0
        ))
    

    (如果您希望结果是数字而不是因子,请使用 as.numeric 包装 derivedFactor . )

    请注意, .default 选项与 .method = "first" 结合设置了"else"条件 - 此方法在 derivedFactor 的帮助文件中进行了描述 .

相关问题