首页 文章

使用多个条件使用dplyr进行变异

提问于
浏览
4

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

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,否则为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() 中使用条件语句,但我似乎无法找到一个例子 . 请指教 .

2 回答

  • 6

    使用 dplyr ,您可以使用:

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

    +(..) 表示法是 as.integer 的简写,用于将逻辑输出强制为1 's and 0' s . 有些人认为代码与可读性相比更短 . 效率增益可以在这种情况下进行辩论 .

    另外要了解 data.tabledplyr 已经用R进行数据操作,让我们以老式的"split-apply-combine"方式做同样的事情:

    #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)
    
  • 5

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

    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
    

    或者我们可以使用 ave 来自 base R

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

相关问题