将列名称传递给函数内的dplyr过滤器函数

时间:2017-04-18 10:32:11

标签: r dataframe dplyr plyr

我正在编写一个函数来为我正在构建的数据框添加一些额外的行。

我已经阅读了很多问题并回答了以前的OP。但是我发现那里的所有答案,提示和技巧都不适用于我。

对于这个问题,我有以下测试数据框:

tst <- data.frame("col 1" = c("a","a", "c"), "keyword test" = c("What", "Why", "how"), check.names = F)
> tst
  col 1 keyword test
1     a         What
2     a          Why
3     c          how

正如你所看到的,我在数据框中有空格我无法删除,因为下一个工具期望列名中有空格(不要问我为什么!)。

现在我希望例如过滤以&#34开头的所有行;&#34;并取代&#34;如何&#34;用&#34; no_idea&#34;。这发生在临时DF内。所以稍后我可以将行"c" "no_idea"添加到原始数据框。

我为此写的功能如下:

add_keyword <- function(df, filterColumn, filterValue,replacement){
  library(plyr)
  library(dplyr)
  temp_df <- dplyr::filter_(df, filterColumn == filterValue)
  temp_df$`Target keyword` <- gsub(as.character(filterValue), as.character(replacement), temp_df$`Target keyword`)
  df_out <- rbind(df, temp_df)
  return(df_out)
}

tst2 <- add_keyword(tst, "keyword test", "how", "no_idea")

当然,如果我在函数外部运行函数,它就可以完美运行。

我想在tst2

中找到的结果
> tst2
  col 1 keyword test
1     a         What
2     a         Why
3     c         how
4     c         no_idea 

3 个答案:

答案 0 :(得分:1)

我们可以使用interp中的lazyeval执行此操作:

library(dplyr)
library(lazyeval)

add_keyword <- function(df, filterColumn, filterValue,replacement){
    temp_df <- df %>%
        filter_(interp(~ var == fval, var = as.name(filterColumn), fval = filterValue))

    temp_df[[filterColumn]] <- gsub(filterValue, replacement = replacement, temp_df[[filterColumn]])
    rbind(df, temp_df)
}
add_keyword(tst, "keyword test", "how", "no_idea")
#   col 1 keyword test
# 1     a         What
# 2     a          Why
# 3     c          how
# 4     c      no_idea

如果我们不想创建其他行,我们也可以尝试:

add_keyword <- function(df, filterColumn, filterValue, replacement){
    df <- df %>%
        mutate_(
            .dots = setNames(
                list(
                    interp(~ ifelse(startsWith(as.character(var), fval), rval, as.character(var)),
                           var = as.name(filterColumn), fval = filterValue, rval = replacement)),
                filterColumn
            )
        )
    df
}
add_keyword(tst, "keyword test", "how", "no_idea")


#   col 1 keyword test
# 1     a         What
# 2     a          Why
# 3     c      no_idea

答案 1 :(得分:1)

我们可以使用dplyr的devel版本(即将发布0.6.0)来使用quosure s

add_keyword <- function(df, filterColumn, filterValue, replacement){
   filterColumn <- enquo(filterColumn)

   filtColumn <- quo_name(filterColumn)
   filterValue <- quo_name(enquo(filterValue))
   replacement <- quo_name(enquo(replacement))

   df %>%
       filter(UQ(filterColumn) ==  filterValue) %>%
       mutate(!!filtColumn  := gsub(filterValue, replacement, !!filterColumn)) %>%
       bind_rows(df, .)


 }

除标准名称外,非自然列名称可以使用反引号传递。

add_keyword(tst, `keyword test`, how, no_idea)
#   col 1 keyword test
#1     a         What
#2     a          Why
#3     c          how
#4     c      no_idea

此处,enquo通过获取输入参数并将其转换为substitute,与base R中的quosure行为类似。我们将quosure转换为quo_name的字符串,并通过取消引用(UQ!!)来评估该值。

检查其他值

add_keyword(tst, `keyword test`, how, new_idea)
#  col 1 keyword test
#1     a         What
#2     a          Why
#3     c          how
#4     c     new_idea

add_keyword(tst, `col 1`, a, z)
#  col 1 keyword test
#1     a         What
#2     a          Why
#3     c          how
#4     z         What
#5     z          Why

数据

tst <- data.frame("col 1" = c("a","a", "c"), "keyword test" = c("What", "Why", "how"),
             check.names = FALSE, stringsAsFactors=FALSE)

答案 2 :(得分:0)

一个简单的技巧,无法解释,只能写下下面的片段:

backend:
 name: bitbucket
 repo: owner-name/repo-name
 branch: default
 auth_type: implicit
 app_id: # The Key from your Bitbucket settings
 publish_mode: editorial_workflow

这对我有用,希望对正在寻找解决方案的你有用:)