【问题标题】:Mutate with dplyr using multiple conditions使用多个条件与 dplyr 进行变异
【发布时间】:2015-10-08 03:38:11
【问题描述】:

我在下面有一个数据框 (df),我想添加一个额外的列 result,如果 z == "gone" 和其中 x 是组 @ 的最大值,则使用 dplyr 将取值 1 987654324@.

   y  x    z
1  a  3 gone
2  a  5 gone
3  a  8 gone
4  a  9 gone
5  a 10 gone
6  b  1     
7  b  2     
8  b  4     
9  b  6     
10 b  7     

如果我只是为每个组选择最大值,那将是:

df %>%
  group_by(y) %>%
  slice(which.max(x))

将返回:

   y  x  z
1  a 10  gone
2  b  7      

这不是我想要的。我需要利用y 中每个组的x 的最大值,同时检查是否z == "gone",如果TRUE 为1,否则为0。这看起来像:

   y  x    z result
1  a  3 gone      0
2  a  5 gone      0
3  a  8 gone      0
4  a  9 gone      0
5  a 10 gone      1
6  b  1           0
7  b  2           0
8  b  4           0
9  b  6           0
10 b  7           0

我假设我会在mutate() 中使用条件语句,但我似乎找不到示例。请指教。

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    使用dplyr,您可以使用:

    df %>% group_by(y) %>% mutate(result = +(x == max(x) & z == 'gone'))
    

    +(..) 表示法是as.integer 的简写,用于将逻辑输出强制为 1 和 0。有些人不喜欢它,所以这是更短的代码与可读性的问题。效率增益可以根据情况进行辩论。

    还要欣赏 data.tabledplyr 对 R 数据处理所做的工作,让我们以老式的“拆分-应用-组合”方式做同样的事情:

    #split data.frame by group
    split.df <- split(df, df$y)
    
    #apply required function to each group
    lst <- lapply(split.df, function(dfx) {
            dfx$result <- +(dfx$x == max(dfx$x) & dfx$z == "gone")
            dfx})
    
    #combine result in new data.frame
    newdf <- do.call(rbind, lst)
    

    【讨论】:

    • 替代代码高尔夫(可以说更具可读性):(x == max(x))*(z == 'gone')
    【解决方案2】:

    我们可以通过data.table 做到这一点。我们将'data.frame'转换为'data.table'(setDT(df)),按'y'分组,我们为'x'的最大值和'z'中的'gone'元素创建逻辑条件,强制它为“整数”(as.integer)并将输出分配(:=)到新列(“结果”)。

    library(data.table)
    setDT(df)[, result := as.integer(x==max(x) & z=='gone') , by = y]
    df
    #    y  x    z result
    # 1: a  3 gone      0
    # 2: a  5 gone      0
    # 3: a  8 gone      0
    # 4: a  9 gone      0
    # 5: a 10 gone      1
    # 6: b  1           0
    # 7: b  2           0
    # 8: b  4           0
    # 9: b  6           0
    #10: b  7           0
    

    或者我们可以使用来自base Rave

    df$result <- with(df, +(ave(x, y, FUN=max)==x & z=='gone' ))
    

    【讨论】:

    • 谢谢!这也可以df %&gt;% group_by(y) %&gt;% mutate(result = ifelse(x == max(x) &amp; z == "gone", 1, 0))
    • @RyanErwin 这也有效,我认为 PierreLafortune 与+(x==max(x) &amp; z=='gone' 的评论对于dplyr 来说应该非常快
    • 谢谢:我不熟悉+( .... )。你知道我在哪里可以找到关于这种语法的文档吗?
    • 用 ave 很好的解决方案
    猜你喜欢
    • 2014-04-15
    • 1970-01-01
    • 2018-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多