【问题标题】:Function to determine proper group确定适当组的功能
【发布时间】:2017-02-23 18:02:54
【问题描述】:

我有以下数据:

DF <- data.frame(Members = c("Eva", "Charlie1", "Fred", "Charlie2", "Adam", "Eva", "Charlie2", "David", "Adam", "David", "Charlie1"))

如果成员名称符合特定条件,我想创建一个返回特定值的函数:

  1. 如果成员名称等于 Eva 或 Adam,则返回“Group1”
  2. 如果成员名称包含字符串“Charlie”,则返回“Group2”
  3. 如果成员名称不是前两条规则之一,则返回“Group3”

我想将“Group1”、“Group2”、“Group3”返回到 DF 中名为“Teams”的新列中

我已经用下面的代码完成了,但是我对如何用函数完成它很感兴趣

DF$Team <- with(DF, ifelse((DF$Members=="Eva"|DF$Members=="Adam"),"Group1",
                       ifelse((grepl("Charlie", DF$Members)),"Group2","Group3")))

【问题讨论】:

  • 您正在使用函数,所以我不太清楚问题是什么。你可以做DF$Team &lt;- factor(DF$Members, labels = ...),但大部分工作是根据你的特殊规则制作这些标签......ifelse 似乎很好。

标签: r function


【解决方案1】:

你的意思是创建一个函数吗?有点像这样:

DF <- data.frame(Members = c("Eva", "Charlie1", "Fred", "Charlie2", "Adam", "Eva", "Charlie2", "David", "Adam", "David", "Charlie1"))

get_group <- function(data=DF, Members=Members) {
  with(DF, ifelse((DF$Members=="Eva"| DF$Members=="Adam"),"Group1",
                  ifelse((grepl("Charlie", DF$Members)),"Group2","Group3")))
}



DF$Group <- get_group(data = DF, Members = Members)

【讨论】:

    【解决方案2】:

    根据我自己的经验,处理此类问题中最具挑战性的部分是“其他所有”部分。我通常很清楚我在别处想要什么。

    常规方法是使用ifelse。这通常是有效的,但我发现很难阅读。我的首选方法是使用类似

    levels(DF$Members) <- list(Group1 = c("Eva", "Adam"),
                               Group2 = c("Charlie1", "Charlie2"),
                               Group3 = c("David", "Fred"))
    

    这种方法的问题是我必须明确命名映射到每个组的所有值。这无助于解决“其他一切”问题。

    我们可以稍微修改这种方法,以编程方式识别组。

    g1 <- c("Eva", "Adam")
    g2 <- levels(DF$Members)[grepl("Charlie", levels(DF$Members))]
    g3 <- levels(DF$Members)[!levels(DF$Members) %in% c(g1, g2)]
    
    levels(DF$Members) <- list(Group1 = g1,
                               Group2 = g2,
                               Group3 = g3)
    

    这是可以容忍的,并且比阅读嵌套的ifelse 调用更能帮助我理解组定义。

    既然你提出来了,我决定最好有一个函数来处理“其他一切”场景而无需我的干预。我想出了以下方法,它允许您命名任意数量的组,然后使用Other = NULL 表示“其他所有内容都进入Other”。

    group_levels <- function(x, ...)
    {
      x <- as.character(x)
    
      group <- list(...)
    
      which_group_null <- vapply(group, is.null, logical(1))
    
      name_null <- names(group)[which_group_null]
    
      group <- group[!which_group_null]
    
      null_group <- list(unique(x[! x %in% unlist(group)]))
      null_group <- setNames(null_group, name_null)
    
      x <- factor(x)
      levels(x) <- c(group, null_group)
      x
    }
    
    group_levels(DF$Members,
                 Group1 = c("Eva", "Adam"),
                 Group2 = levels(DF$Members)[grepl("Charlie", levels(DF$Members))],
                 Group3 = NULL)
    

    如果您省略了Group3 = NULL,则会为不匹配的级别提供NA 值。

    它可能比使用ifelse 慢,但我喜欢它的阅读方式。

    【讨论】:

      【解决方案3】:

      也许你的意思是:

      group_function <- function(name_string) {
          if (name_string == "Eva" | name_string == "Adam")
              return("Group 1")
          if (grepl("Charlie", name_string))
              return("Group 2")
          return("Group 3")
       }
      

      然后在每个成员上调用这个函数

      DF$Team <- sapply(DF$Members, group_function)
      DF
      
      #    Members    Team
      #1       Eva Group 1
      #2  Charlie1 Group 2
      #3      Fred Group 3
      #4  Charlie2 Group 2
      #5      Adam Group 1
      #6       Eva Group 1
      #7  Charlie2 Group 2
      #8     David Group 3
      #9      Adam Group 1
      #10    David Group 3
      #11 Charlie1 Group 2
      

      【讨论】:

      • 在会员级别而不是每个单独的元素上执行此操作应该更有效(假设级别重复很多)。
      猜你喜欢
      • 1970-01-01
      • 2015-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多