【问题标题】:Collapsing multiple factor levels of (messy) character variable in R在R中折叠(混乱)字符变量的多个因子级别
【发布时间】:2020-03-30 14:34:38
【问题描述】:

我很难在 R Studio 中将多个因子水平折叠成一个特定变量的三个因子水平。

我的出发点是data.table,它有 250 个变量和大约 4,000 行。对于一个因素变量,我想将它的 75 个级别合并为 3 个级别。此外,在 75 个级别中,应忽略 4 个级别(或之前设置为 NA),因为它们包含有争议的信息。该因子变量基于调查答案,其中还包括文本格式的个人答案。有时甚至语言也不同。所以,有点乱。

我尝试以两种不同的方式将这 75 个级别(或者如果之前分别设置为 NA 的情况下为 71 个级别)折叠成 3 个级别。但是,R 总是在控制台中返回 + 而不是 >,我无法继续执行任何其他命令。当然,我可以通过点击Esc 来阻止这种情况,但这并不能帮助我获得想要的结果。

所以,这个虚构的例子应该显示我尝试过的内容:

1) 使用levelslist 函数

levels(dt$x) <- list("No"=c("I don't allow anything", "..."), 
"Yes"= c("Number of visitors ,annual sales, sales growth, number of customers", "Net sales", "..."), 
"Maybe"=c("The CEO's approval is needed.", "To be discussed"))

2) 使用forcats

dt$x %>%
fct_collapse(No= c("I don't allow anything", "..."), 
Yes= c("Number of visitors ,annual sales, sales growth", "number of customers", "Net sales", "..."), 
Maybe=c("The CEO's approval is needed.", "To be discussed"))

我认为问题是由原始变量的结构引起的。有谁知道我该如何解决这个问题?

非常感谢您!

最好, 伊尔卡

【问题讨论】:

    标签: r character factors levels


    【解决方案1】:

    dt$x 肯定是一个“因素”。要将不同的值分配给因子列,应首先将数据转换为“字符”类型

    class(dt$x) # should be factor
    dt$x <- as.character(dt$x)
    class(dt$x) # should be "character"  
    
    # a list of collapsed Categories
    toCollapseCategories <- list(
        "No"=c("I don't allow anything", "..."), 
        "Yes"= c("Number of visitors ,annual sales, sales growth, number of customers", "Net 
               sales", "..."), 
        "Maybe"=c("The CEO's approval is needed.", "To be discussed")
    )
    
    dt$x[dt$x %in% toCollapseCategories$No] <- "No"
    dt$x[dt$x %in% toCollapseCategories$Yes] <- "Yes"
    dt$x[dt$x %in% toCollapseCategories$Maybe] <- "Maybe"
    
    # and then get a factor
    dt$x <- as.factor(dt$x)
    class(dt$x) # factor
    

    当然,代码可以优化,但 dt$x 应该是一个字符才能替换元素

    【讨论】:

    • 谢谢你的想法,马塞洛。我尝试了它,首先它似乎运作良好,但不知何故我最终得到了 7 个级别而不是 3 个。我猜其中一个是 NA,也许其他级别以某种方式翻了一番?无论如何,正如我刚刚发布的那样,一位朋友实际上向我展示了如何克服我的挑战。
    【解决方案2】:

    我的一个朋友实际上提供了答案。与数据结构无关。

    这样就可以了:

    dt$x <- fct_collapse(dt$x, 
                              No = c(
                                "I don't allow anything", 
                                 "..."),
                              Yes= c(
                                 "Number of visitors ,annual sales, sales growth",
                                 "number of customers", 
                                 "Net sales", 
                                 "..."),
                              Maybe= c(
                                  "The CEO's approval is needed.", 
                                  "To be discussed")
                                   )
    

    我仍然不知道为什么我在上面发布的第一个选项不起作用(它与另一个变量完美匹配)。

    【讨论】:

    • 请注意,如果要排除某些级别,则需要先将这些观测值设置为 NA,然后再将变量设为因子(或将其设为字符,将观测值设为 NA,然后将其设为因子再次)。在变量是一个因素的情况下执行此操作时,这些水平仍将存在于新变量中,但观察值为 0。
    【解决方案3】:

    我在 github 上写了一个函数 xfactor 来帮助解决这种情况。它允许使用正则表达式匹配重新编码因子级别,因此对于处理混乱的数据很有用。它还允许您使用“排除”语句通过正则表达式匹配删除因子级别。

    devtools::install_github("jwilliman/xfactor")
    library(xfactor)
    
    dt$x <- xfactor::xfactor(dt$x, levels = c(
      No = "don't|never",
      Yes = "sales|visitors|customers",
      Maybe = "approval|discuss"),
      exclude = "irrelevant", ignore.case = TRUE)
      )
    

    更多示例请参见https://stackoverflow.com/a/37800944/4241780

    顺便说一句,如果 R 在控制台中返回 + 而不是 &gt;,您可能在某处错过了关闭 )"

    【讨论】:

    • 非常感谢您的回答 JWilliman。我尝试它只是为了看看它是否有效(我已经得到了我在上面发布的正在运行的解决方案)。 1)代码末尾缺少一个括号。尝试您的包时仍然出现以下错误“操作只能用于数字、逻辑或复杂类型”
    • 我一开始就写错了No="don't"|"never"等,所以想用这个方案的朋友要注意一定要No="don' t|never”等。但是,我认为您的代码 JWilliman 不适用于非常相似的输入。我收到错误“警告消息:多个匹配项:”在我的数据中,所有可能的答案在变量中一个接一个地列出,并且 2 个或多个观察结果可能有 10 个相似条目,并且仅相差 1 个条目。
    • @Ilka 感谢您的尝试。错误消息是警告您单个条目与多个不同级别匹配(例如,在上面的示例中,“我没有客户”将与“否”和“是”匹配)。您需要更改您的正则表达式以防止多次匹配 - 但是听起来您的数据可能最适合使用 fct_collapse 进行绝对匹配,而不是使用正则表达式进行模糊匹配。
    猜你喜欢
    • 2013-10-24
    • 2020-02-21
    • 1970-01-01
    • 2016-12-11
    • 1970-01-01
    • 2019-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多