【问题标题】:Problem collapsing levels of a factor in R问题在R中折叠一个因子的水平
【发布时间】:2021-02-22 19:41:17
【问题描述】:

我有一个杂乱无章的因子变量,其级别超出了应有的级别。这些案例来自一项公开调查,许多参与者写错字或只是以不同的方式回答了类似的答案。

这是代表我的问题的示例 df:


df <- data.frame(ID=seq(1:10),
                 Nationality=c("espanol", "spaniol", "ESPANOL",
                               "spanish", "colombia", "Colombian",
                               "British", "brit", "ESPanol", "UK")
                               )

我想要的输出是这样的:

> df
   ID Nationality
1   1     Spanish
2   2     Spanish
3   3     Spanish
4   4     Spanish
5   5   Colombian
6   6   Colombian
7   7     British
8   8     British
9   9     Spanish
10 10     British

这是我试图做的,以便将这 10 个人为因素的水平减少到只有 3 个(西班牙、哥伦比亚、英国),因为它应该是:

library(forcats) 
                              
levels(df$Nationality) <- fct_collapse(df$Nationality, Spanish = c("espanol", "spaniol", "ESPANOL",
                                                                  "spanish", "ESPanol"),
                                                       Colombian = c("colombia", "Colombian"),
                                                       British = c("British", "brit", "UK")
                                        )

这有效地将我的“国籍”因素降低到 3 个级别,但输出看起来像这样,并且与第一个类似:

> df
   ID Nationality
1   1   Colombian
2   2     British
3   3     British
4   4     Spanish
5   5     Spanish
6   6     Spanish
7   7     Spanish
8   8     Spanish
9   9   Colombian
10 10     British

在我正在使用的更大数据集中,它也不起作用,但输出更糟,因为所有案例都变成了“西班牙”,我不知道为什么会发生这种情况。

提前感谢您的帮助! 最好的, 卢卡斯

【问题讨论】:

    标签: r r-factor


    【解决方案1】:

    您是否尝试过首先将国籍作为一个因素?

    df <- data.frame(ID=seq(1:10),
                     Nationality=c("espanol", "spaniol", "ESPANOL",
                                   "spanish", "colombia", "Colombian",
                                   "British", "brit", "ESPanol", "UK")
    )
    library(forcats) 
    
    
    df2 <- df %>% 
      mutate(Nationality = factor(Nationality)) %>% 
     mutate(Nationality = fct_collapse(Nationality, Spanish = c("espanol", "spaniol", "ESPANOL", "spanish", "ESPanol"),
                                           Colombian = c("colombia", "Colombian"),
                                           British = c("British", "brit", "UK")))
    
    
    
    #more concise
    
    mutate(across(Nationality, ~ fct_collapse(factor(.), 
    Spanish = c("espanol", "spaniol", "ESPANOL", "spanish", "ESPanol"), 
    Colombian = c("colombia", "Colombian"), 
    British = c("British", "brit", "UK")
    ))) 
    

    【讨论】:

    • mutate_across(Nationality, ~ fct_collapse(factor(.), Spanish=...))
    • mutate_* 现在已弃用。变异(跨越(国籍,〜fct_collapse(因子(。),西班牙语= c(“espanol”,“西班牙人”,“西班牙人”,“西班牙人”,“西班牙人”),哥伦比亚人= c(“哥伦比亚”,“哥伦比亚” ), British = c("British", "brit", "UK")))))
    • 抱歉,下划线是错字。 (我知道mutate_* 已被弃用:mutate_across() 曾经存在吗?)
    • 谢谢,这很好用。但是,我很困惑......我从未明确将我的变量声明为一个因素,但唯一的原因是因为当使用str(df$Nationality) 时,输出告诉我这已经是一个因素。这怎么可能?
    • 正如我在其他答案中提到的,您的代码解决了这个问题。但是,问题从来不是它以前不是一个因素,旧版本的 R 之前将其视为一个因素,并且使用相同的代码将其更改为之前的因素不会给出预期的输出。我很好奇我的代码无法正常工作的原因,所以我从错误中吸取了教训。谢谢!
    【解决方案2】:

    以下是一些使用内置函数的解决方案:

    解决方案 1

    此解决方案假定列 Nationality 是一个字符变量

    cases <- c(espanol = "Spanish", spaniol = "Spanish", ESPANOL = "Spanish", spanish = "Spanish", 
               British = "British", brit = "British", ESPanol = "Spanish", UK = "British",
               colombia = "Colombian", Colombian = "Colombian")
    
    df$Nationality <- factor(cases[df$Nationality])
    

    解决方案 2

    df$Nationality <- as.factor(df$Nationality)
    
    levels(df$Nationality) <- list(Spanish = c("espanol", "spaniol", "ESPANOL", "spanish", "ESPanol"),
                                   Colombian = c("colombia", "Colombian"),
                                   British = c("British", "brit", "UK"))
    

    输出数据

    #    ID Nationality
    # 1   1     Spanish
    # 2   2     Spanish
    # 3   3     Spanish
    # 4   4     Spanish
    # 5   5   Colombian
    # 6   6   Colombian
    # 7   7     British
    # 8   8     British
    # 9   9     Spanish
    # 10 10     British
    

    【讨论】:

    • 谢谢,这也有效。但是,问题似乎与我没有将 df$Nationality 转换为因子相同。我不明白,因为它应该是str(df$Nationality)function 显示的一个因素。
    • 请注意,您的问题有歧义。在描述它时,您谈到了因子变量,但在可重现的示例中,您提供了变量 Nationality 作为字符。最好提供它作为一个因素。如果您的变量已经是一个因素,那么您只需要解决方案 2 的第二部分。
    • 这是因为我对 R 不是很精通,因为我刚开始不久。我知道除非指定,否则字符串在 R 中被视为字符,但我不明白为什么会发生这种情况:str(df$Nationality)Factor w/ 10 levels "brit","British",..: 5 8 7 9 3 4 2 1 6 10
    • 这很可能是因为您使用的 R 版本早于 4.0.0。从 R 4.0.0 开始,data.frame 参数 stringsAsFactors 的默认值已从 TRUE 更改到FALSE。运行R.version.string 以检查您正在使用的版本。如果它早于 4.0.0(即它以小于 4 的数字开头),那么您需要在创建 data.set 时向data.frame 函数添加一个附加参数data.frame 以读取字符变量这样.. 类似 `df
    • 继续:类似df &lt;- data.frame(ID=..., Nationality=..., stringsAsFactors = FALSE)
    猜你喜欢
    • 1970-01-01
    • 2020-11-13
    • 1970-01-01
    • 2016-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    相关资源
    最近更新 更多