【问题标题】:R - changing factors to numerics with specific mappingsR - 将因子更改为具有特定映射的数字
【发布时间】:2014-03-30 04:29:16
【问题描述】:

假设我读过一个数据框,其中一列包含字符串作为因子。我想将因子转换为数字,但要使用特定映射。这种转换通常是稍后计算的前导步骤。例如:

> library(rpart)

> head(car90["Type"])
                 Type
Acura Integra   Small
Acura Legend   Medium
Audi 100       Medium
Audi 80       Compact
BMW 325i      Compact
BMW 535i       Medium

> summary(car90$Type)
Compact   Large  Medium   Small  Sporty     Van    NA's 
     19       7      26      22      21      10       6

在 car90$Type 列中,我想将“Compact”设置为 -10,“Large”设置为 -1,“Medium”设置为 0,“Small”设置为 1,“Sporty”设置为10 和 'Van' 为 20,其中数字是数字,而不是因子。我该怎么做?

我已经查看了相关问题,但没有一个提供解决方案。

Replace specific column "words" into number or blank

Changing column names of a data frame in R

Replace contents of factor column in R dataframe

Convert factor to integer

【问题讨论】:

    标签: r dataframe


    【解决方案1】:

    我只会使用向量下标;这是一个例子:

    R>a <- as.factor(c("C", "L", "M", "L", "C"))
    R>a
    [1] C L M L C
    Levels: C L M
    R>b <- c(C=-10,L=-1,M=0)
    R>b
      C   L   M 
    -10  -1   0 
    R>
    R>b[a]
      C   L   M   L   C 
    -10  -1   0  -1 -10 
    R>
    

    【讨论】:

      【解决方案2】:

      你可以试试这个

      x <- c('Compact', 'Large', 'Medium', 'Small', 'Sporty', 'Van') 
      y <-  factor(x, levels = c('Compact', 'Large', 'Medium', 'Small', 'Sporty', 'Van'), 
          labels = c(-10, -1, 0, 1, 10, 20))
      as.numeric(as.character(y))
      
      
      [1] -10  -1   0   1  10  20
      

      对于您的情况,您可以致电:

      car90$Type <-  factor(car90$Type, levels = c('Compact', 'Large', 'Medium', 'Small', 'Sporty', 'Van'), 
          labels = c(-10, -1, 0, 1, 10, 20))
      car90$Type <-  as.numeric(as.character(car90$Type))
      

      【讨论】:

      • 我仍然需要将其保存回数据框中,对吧?我会做car90$Type &lt;- as.numeric(as.character(y))吗?
      • 谢谢。但 car90$Type 已经是一个因素。有什么方法可以在第一步中只分配标签而不是将 car90$Type 设置为新因素?
      • 我建议避免直接将标签分配给一个因素。创造一个新的因素会更安全,避免很多潜在的问题。您可能需要检查结果并调用 as.character 将因子转换为字符,然后再转换一个新因子。
      【解决方案3】:

      正如@NealFultz 所说,向量下标可以实现这一点。但是,您必须小心如何执行此操作:

      x <- car90$Type[1:10]
      #[1] Small   Medium  Medium  Compact Compact Medium  Medium  Large   Large   <NA>
      #Levels: Compact Large Medium Small Sporty Van
      

      即:

      vals <- c(Compact=-10,Large=-1,Medium=0,Small=1,Sporty=10,Van=20)
      vals[x]
      

      将给出正确的结果,因为 vals 中的顺序与 x 因子中的 levels 相同:

      vals[x]
      #  Small  Medium  Medium Compact Compact  Medium  Medium   Large   Large    <NA> 
      #      1       0       0     -10     -10       0       0      -1      -1      NA 
      

      如果你更改vals中的顺序,这将失败,例如:

      vals <- c(Large=-1,Compact=-10,Medium=0,Small=1,Sporty=10,Van=20)
      vals[x]
      #  Small  Medium  Medium   Large   Large  Medium  Medium Compact Compact    <NA> 
      #      1       0       0      -1      -1       0       0     -10     -10      NA 
      

      您可以通过将x 中的字符表示与valsnames 进行比较而不是顺序来解决此问题,例如:

      vals <- c(Large=-1,Compact=-10,Medium=0,Small=1,Sporty=10,Van=20)
      vals[as.character(x)]
      #  Small  Medium  Medium Compact Compact  Medium  Medium   Large   Large    <NA> 
      #      1       0       0     -10     -10       0       0      -1      -1      NA 
      

      【讨论】:

        【解决方案4】:

        这是一个连接操作

        encode <- data.frame(Type = c("Compact", "Large", "Medium", "Small", "Sporty", "Van"), TypeValue = c(-10,-1,0,1,10,20))
        
        car90 <- merge(car90, encode, all.x = TRUE)
        
        # or using dplyr
        library(dplyr)
        car90 <- left_join(car90, encode)
        

        【讨论】:

          【解决方案5】:

          使用merge(),如下例所示。

          首先使用您想要的值创建一个数据框。在这种情况下,你会写

           dictionary <- data.frame(Type = c('Compact', 'Large', 'Medium', 'Small', 'Sporty', 'Van'),
                               Values = c(-10, -1, 0, 1, 10, 20))
          
           output <- merge(car90$Type, dictionary)
          

          重要提示:此示例未考虑 NA。如果您也想给它们一个值,则需要将其作为具有自己值的类型包含在内。否则这些行将不会成为输出的一部分。

          并且生成的数据框按照您的需要进行格式化。

          注意:如果列的名称完全相同会更容易,但您可以定义要与 by.x 和 by.y 一起使用的列,请查看文档以获取更多信息。

          【讨论】:

            【解决方案6】:

            只需重置关卡:

            levels(car90$Type) <- c(-10, -1, 0, 1, 10, 20)
            

            导致(与您相同的头部/子集):

            #               Type
            # Acura Integra    1
            # Acura Legend     0
            # Audi 100         0
            # Audi 80        -10
            # BMW 325i       -10
            # BMW 535i         0
            

            尽管小心,如果您打算对此进行计算,则必须as.numeric(levels(fac))[fac] 确保您计算的是数字,而不是基础因子整数值。

            【讨论】:

              猜你喜欢
              • 2022-01-16
              • 1970-01-01
              • 2014-07-17
              • 2012-01-25
              • 2022-07-23
              • 1970-01-01
              • 2017-05-13
              • 2022-07-12
              相关资源
              最近更新 更多