【问题标题】:Creating new variables with dplyr::mutate() without conflicting names使用 dplyr::mutate() 创建新变量而不冲突名称
【发布时间】:2019-08-08 20:29:14
【问题描述】:

我正在编写一系列在内部使用dplyr 来操作数据的函数。

在处理数据集时,我想在很多地方添加新变量。但是,我不确定如何命名这些新变量以避免覆盖数据中已经存在的变量,因为我不知道正在传递的数据集中有什么。

在基础 R 中我可以这样做:

df <- data.frame(a = 1:5)

df[, ncol(df)+1] <- 6:10

它将为新添加的变量选择一个不与任何现有名称冲突的名称。我想在dplyr 中执行此操作,而不是打破dplyr 的一致应用程序以返回base-R。

到目前为止,我想到的所有解决方案都感觉非常笨拙,或者无论如何都需要使用一堆 base-R futzing,这并不比在 base-R 中添加变量更好:

  1. 重命名所有变量,以便我知道名称是什么
  2. 拉出names() 向量并使用多种方法之一来生成不在向量中的名称
  3. 如果用户碰巧在他们的数据中包含我的内部变量名,则会出错(糟糕的做法奥运会!)

dplyr 中是否有直接的方法来执行此操作?让它在 mutate 中工作是理想的,尽管我认为 bind_colstibble::add_column 也可以。

我尝试过的一些方法不起作用:

df <- data.frame(a = 1:5)

# Gives the new variable a fixed title which might already be in there
df %>% mutate(6:10)
df %>% tibble::add_column(6:10)
df %>% mutate(NULL = 6:10)

# Error
df %>% bind_cols(6:10)
df %>% mutate( = 6:10)
df %>% mutate(!!NULL := 6:10)

# And an example of the kind of function I'm looking at:
# This function returns the original data arranged in a random order
# and also the random variable used to arrange it
arrange_random <- function(df) {
  df <- df %>%
    mutate(randomorder = runif(n())) %>%
    arrange(randomorder)

  return(df)
}

# No naming conflict, no problem!
data <- data.frame(a = 1:5)
arrange_random(data)

# Uh-oh, the original data gets lost!
data <- data.frame(randomorder = 1:5)
arrange_random(data)

【问题讨论】:

  • 能否请您提供一个 min reprex 并包括您尝试过的内容和一些示例数据? stackoverflow.com/help/minimal-reproducible-example
  • 你可以让用户指定一个不冲突的前缀作为你的函数的参数,然后添加简单的后缀,例如_1,_2,...?如果用户未指定该参数,您可能会有一个默认值,如果名称冲突,则会出现一个错误,要求用户使用指定的该参数重新运行。我认为不应该让他们太困惑。
  • @kstew 我添加了一个小例子和一些我已经尝试过的失败尝试。
  • Nick,你说你想在函数中添加新变量,你能提供更多关于函数的细节吗?

标签: r dplyr


【解决方案1】:

我现在发布这个解决方案。这听起来像是不太了解自己的数据的情况,所以我认为一种好的方法是在函数中包含if-else 语句。逻辑是用户选择一些任意新名称作为其原始变量名称的后缀,但如果新名称已包含在原始数据中,则该函数将返回错误。否则,函数运行并返回原始数据和新变化的数据。

df <- data.frame(a = 1:5, b=11:15, c=21:25)

# define function with if-else statement to catch any possible duplicates
addnew <- function(data,name='newvar'){
  if(sum(grepl(name,names(data),ignore.case=T))>0)
  {stop('Error! Possible duplicate names with your new variable names')} else{
  data1 <- data %>% mutate_all(list( ~ runif(n())))
  names(data1) <- paste0(names(data1),'_',name)
  bind_cols(data,data1)
    }
}

addnew(df,'new')

  a  b  c     a_new     b_new     c_new
1 1 11 21 0.2875775 0.0455565 0.9568333
2 2 12 22 0.7883051 0.5281055 0.4533342
3 3 13 23 0.4089769 0.8924190 0.6775706
4 4 14 24 0.8830174 0.5514350 0.5726334
5 5 15 25 0.9404673 0.4566147 0.1029247

# try with new data that should throw an error
df <- data.frame(a_new = 1:5,b=11:15,c=21:25)

addnew(df,'new')
Error in addnew(df, "new") : 
  Error! Possible duplicate names with your new variable names

【讨论】:

    猜你喜欢
    • 2018-08-13
    • 2018-10-03
    • 1970-01-01
    • 2018-11-11
    • 2018-02-20
    • 2016-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多