【问题标题】:R dplyr method mutate variable if existsR dplyr 方法变异变量(如果存在)
【发布时间】:2018-01-19 16:41:35
【问题描述】:

作为 dplyr 及其整洁数据概念的忠实拥护者,我想在数据帧中存在特定变量时对其进行变异。思路是这样的:

# Load libraries
library(dplyr)

# Create data frames
df1 <- data.frame(year = 2000:2010, foo = 0:10)
df2 <- data.frame(year = 2000:2010)

# Create function
cnd_mtt <- function(df){
  df %>%
    mutate_if(colname == "foo", as.factor) # <---- this is the tricky part
}

预期结果:该函数应该适用于两个数据帧并且没有错误

想法?

【问题讨论】:

  • colname 是什么?
  • if 声明怎么样:if("foo" in names(df)) ...
  • @Gregor 必须是%in%,看我的回答

标签: r dplyr


【解决方案1】:

您可以将mutate_atone_of 一起使用,如果该列不存在,则会引发警告消息:

cnd_mtt <- function(df){
    df %>%
        mutate_at(vars(one_of('foo')), as.factor)
}

cnd_mtt(df2)
#   year
#1  2000
#2  2001
#3  2002
#4  2003
#5  2004
#6  2005
#7  2006
#8  2007
#9  2008
#10 2009
#11 2010
Warning message:
Unknown variables: `foo`

澄清一下,当one_of 无法从vars 变量解析列名时,会发出警告消息:

one_of('foo', vars = names(df1))
# [1] 2
one_of('foo', vars = names(df2))
# integer(0)
Warning message:
Unknown variables: `foo`

如果您想进一步摆脱警告消息,请接受@Gregor 的评论,您可以使用mutate_atif/else,如果列中不存在foo,则返回integer(0)

df2 %>% 
    mutate_at(if('foo' %in% names(.)) 'foo' else integer(0), as.factor)

#   year
#1  2000
#2  2001
#3  2002
#4  2003
#5  2004
#6  2005
#7  2006
#8  2007
#9  2008
#10 2009
#11 2010

【讨论】:

  • 非常感谢。效果很好!
【解决方案2】:

在 Psidom 答案的基础上,您还可以使用 quietly 来避免警告:

df2 %>%
  mutate_at(vars(quietly(one_of)("foo","boo",  .vars = tidyselect::peek_vars())$result),
            as.factor)

【讨论】:

    【解决方案3】:

    使用基本的管道操作,我相信不受 dplyr 的束缚。也尽量不要使用df作为变量名

    # Load libraries
    library(dplyr)
    
    # Create data frames
    df1 <- data.frame(year = 2000:2010, foo = 0:10)
    df2 <- data.frame(year = 2000:2010)
    
    # Create function
    cnd_mtt <- function(dff,colname){
        if (colname %in% names(dff)){
            dff%>%mutate(new_col=some.transformation)
        }
    }
    

    【讨论】:

    • 这个解决方案在函数(整洁数据概念)中的许多其他管道(%>%)上效果不佳。 Psidoms 的回答对我有好处。
    猜你喜欢
    • 2018-11-30
    • 2018-08-22
    • 1970-01-01
    • 2020-08-13
    • 1970-01-01
    • 2021-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多