【问题标题】:How to concatenate factors, without them being converted to integer level?如何连接因子,而不将它们转换为整数级别?
【发布时间】:2011-03-27 11:50:45
【问题描述】:

我很惊讶地看到 R 在连接向量时会将因子强制转换为数字。即使级别相同,也会发生这种情况。例如:

> facs <- as.factor(c("i", "want", "to", "be", "a", "factor", "not", "an", "integer"))
> facs
[1] i       want    to      be      a       factor  not     an      integer
Levels: a an be factor i integer not to want
> c(facs[1 : 3], facs[4 : 5])
[1] 5 9 8 3 1

在 R 中执行此操作的惯用方法是什么(在我的情况下,这些向量可能非常大)?谢谢。

【问题讨论】:

    标签: r concatenation r-factor


    【解决方案1】:

    来自R Mailing list

    unlist(list(facs[1 : 3], facs[4 : 5]))
    

    要'cbind'因素,做

    data.frame(facs[1 : 3], facs[4 : 5])
    

    【讨论】:

      【解决方案2】:

      另一种解决方法是将因子转换为字符向量,然后在完成连接时转换回来。

      cfacs <- as.character(facs)
      x <- c(cfacs[1:3], cfacs[4:5]) 
      
      # Now choose between
      factor(x)
      # and
      factor(x, levels = levels(facs))
      

      【讨论】:

        【解决方案3】:

        使用forcats 包中的fct_ctidyverse 的一部分)。

        > library(forcats)
        > facs <- as.factor(c("i", "want", "to", "be", "a", "factor", "not", "an", "integer"))
        > fct_c(facs[1:3], facs[4:5])
        [1] i    want to   be   a
        Levels: a an be factor i integer not to want
        

        fct_c 不会被数字编码不一致的因子串联所迷惑:

        > x <- as.factor(c('c', 'z'))
        > x
        [1] c z
        Levels: c z
        > y <- as.factor(c('a', 'b', 'z'))
        > y
        [1] a b z
        Levels: a b z
        > c(x, y)
        [1] 1 2 1 2 3
        > fct_c(x, y)
        [1] c z a b z
        Levels: c z a b
        > as.numeric(fct_c(x, y))
        [1] 1 2 3 4 2
        

        【讨论】:

        • 对我来说,这个答案是正确给出预期输出的答案!。很棒
        【解决方案4】:

        哇,我从来没有意识到它会那样做。这是一个解决方法:

        x <- c(facs[1 : 3], facs[4 : 5]) 
        x <- factor(x, levels=1:nlevels(facs), labels=levels(facs))
        x
        

        输出:

        [1] i    want to   be   a   
        Levels: a an be factor i integer not to want
        

        只有当两个向量的级别与此处相同时,它才会起作用。

        【讨论】:

        • 非常感谢!我刚刚发现 unlist(list(facs[1 : 3], facs[4 : 5])) 也可以工作,如果您不提前知道 facs 是一个因子类型,这很好。
        • 以这种方式手动设置级别不适用于我的特定问题。 (我有基于 0 的级别。我本可以减去 1,然后重建该因子,但是,即使对于 R,它也是脆弱的,并且在可审查性频谱的较小端。)相反(万岁?)我选择了 unlist(list(...)) .
        【解决方案5】:

        这是一个非常糟糕的 R 问题。沿着这些思路,这里有一个刚刚占用了我几个小时的时间。

        x <- factor(c("Yes","Yes","No", "No", "Yes", "No"))
        y <- c("Yes", x)
        
        > y
        [1] "Yes" "2"   "2"   "1"   "1"   "2"   "1"  
        > is.factor(y)
        [1] FALSE
        

        在我看来,更好的解决方法是 Richie's,它会强制角色。

        > y <- c("Yes", as.character(x))
        > y
        [1] "Yes" "Yes" "Yes" "No"  "No"  "Yes" "No" 
        > y <- as.factor(y)
        > y
        [1] Yes Yes Yes No  No  Yes No 
        Levels: No Yes
        

        正如 Richie 所说,只要您正确设置了关卡。

        【讨论】:

          【解决方案6】:

          基于使用转换为字符的其他答案,我正在使用以下函数来连接因子:

          concat.factor <- function(...){
            as.factor(do.call(c, lapply(list(...), as.character)))
          }
          

          您可以像使用 c 一样使用此函数。

          【讨论】:

            【解决方案7】:

            出于这个原因,我更喜欢使用 data.frames 中的因素:

            df <- data.frame(facs = as.factor(
                  c("i", "want", "to", "be", "a", "factor", "not", "an", "integer") ))
            

            并使用 subset() 或 dplyr::filter() 等而不是行索引对其进行子集化。因为在这种情况下我没有有意义的子集标准,所以我将只使用 head() 和 tail():

            df1 <- head(df, 4)
            df2 <- tail(df, 2)
            

            然后你可以很容易地操纵它们,例如:

            dfc <- rbind(df1, df2)
            dfc$facs
            #[1] i       want    to      be      an      integer
            #Levels: a an be factor i integer not to want
            

            【讨论】:

              【解决方案8】:

              请注意,从 R 4.1.0 开始,这直接在基础 R 中解决。您现在可以直观地做到这一点

              c(facs[1 : 3], facs[4 : 5])
              

              【讨论】:

                【解决方案9】:

                当设置稍有不同时,这是添加到因子变量的另一种方法:

                facs <- factor(1:3, levels=1:9,
                               labels=c("i", "want", "to", "be", "a", "factor", "not", "an", "integer"))
                facs
                # [1] i       want    to      be      a       factor  not     an      integer
                # Levels: a an be factor i integer not to want
                facs[4:6] <- levels(facs)[4:6]
                facs
                # [1] i      want   to     be     a      factor
                # Levels: i want to be a factor not an integer
                

                【讨论】:

                  猜你喜欢
                  • 2016-12-01
                  • 1970-01-01
                  • 2015-09-18
                  • 2017-05-14
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多