【问题标题】:R factor with two types as numericR因子有两种类型作为数字
【发布时间】:2017-11-12 09:53:20
【问题描述】:

我在 R 中有一个包含 49 个级别的因子,我正在尝试使用 as.numeric 将其转换为数字

  • 纬度:系数“0.80N”、“0.40S”、...

我希望将北指定转换为“+”,将南指定为“-”,以便数据看起来像

  • 纬度:num 0.80, -0.40, ...

我不知道以后该怎么做

Mcity$lat <- as.numeric(Mcity$Latitude)



structure(c(40L, 40L, 40L, 40L), .Label = 
  c("0.80N", "0.80S", "10.45N", "12.05N", "12.05S", "13.66N", "13.66S",
    "15.27N", "15.27S", "16.87N", "18.48N", "18.48S", "2.41N", "20.09N", 
    "20.09S", "21.70N", "23.31N", "23.31S", "24.92N", "26.52N", "28.13N", 
    "29.74N", "29.74S", "31.35N", "32.95N", "32.95S", "34.56N", "34.56S", 
    "36.17N", "37.78N", "37.78S", "39.38N", "4.02N", "4.02S", "40.99N", "42.59N", 
    "44.20N", "45.81N", "49.03N", "5.63N", "5.63S", "50.63N", "52.24N", "55.45N", 
    "60.27N", "7.23N", "7.23S", "8.84N", "8.84S"), class = "factor") 

【问题讨论】:

  • 在您的问题中包含minimal reproducible example 会增加您获得答案的机会。
  • 这样的? > dput(head(Mcity$Latitude,4))
  • 结构(c(40L, 40L, 40L, 40L), .Label = c("0.80N", "0.80S", "10.45N", "12.05N", "12.05S" 、“13.66N”、“13.66S”、“15.27N”、“15.27S”、“16.87N”、“18.48N”、“18.48S”、“2.41N”、“20.09N”、“20.09S” 、“21.70N”、“23.31N”、“23.31S”、“24.92N”、“26.52N”、“28.13N”、“29.74N”、“29.74S”、“31.35N”、“32.95N” 、“32.95S”、“34.56N”、“34.56S”、“36.17N”、“37.78N”、“37.78S”、“39.38N”、“4.02N”、“4.02S”、“40.99N” 、“42.59N”、“44.20N”、“45.81N”、“49.03N”、“5.63N”、“5.63S”、“50.63N”、“52.24N”、“55.45N”、“60.27N” , "7.23N", "7.23S", "8.84N", "8.84S"), class= "因子")
  • 真的 认为这是 stackoverflow.com/questions/14359115/… 的重复,但如果我以这种方式标记它而无需确认,它将关闭 q,我不确定这是有保证的由于输入格式略有不同。
  • @hrbrmstr,肯定是非常接近。你可以争辩说,如果有人查了这个问题,他们很容易适应。唯一的区别是将字符串分成几部分......但同样,也有很多问题可以解决。

标签: r numeric levels


【解决方案1】:

这应该可行:

Mcity$lat <- (1 - 2 * grepl("S", Mcity$Latitude)) * as.numeric(gsub("N|S", "", Mcity$Latitude))

如果它找到一个 S,它会改变数字部分的符号。

【讨论】:

    【解决方案2】:

    您可以使用stringr 删除最后一个字符,然后使用dplyr 作为重新组合的选项,我使用case_when 提供额外的错误处理,但ifelse 就足够了。

    library(dplyr)
    library(stringr)
    
    fct_list <- factor(
      c(
        "0.80N", "0.80S", "10.45N", "12.05N", "12.05S", "13.66N", "13.66S",
        "15.27N", "15.27S", "16.87N", "18.48N", "18.48S", "2.41N", "20.09N",
        "20.09S", "21.70N", "23.31N", "23.31S", "24.92N", "26.52N", "28.13N",
        "29.74N", "29.74S", "31.35N", "32.95N", "32.95S", "34.56N", "34.56S",
        "36.17N", "37.78N", "37.78S", "39.38N", "4.02N", "4.02S", "40.99N",
        "42.59N", "44.20N", "45.81N", "49.03N", "5.63N", "5.63S", "50.63N",
        "52.24N", "55.45N", "60.27N", "7.23N", "7.23S"
      )
    )
    
    # note that factors are often no fun, so I've converted to character here
    string <- as.character(fct_list)
    
    case_when(
      str_sub(string, -1, -1) == "N" ~ as.numeric(str_sub(string, 1, nchar(string) - 1)),
      str_sub(string, -1, -1) == "S" ~ -as.numeric(str_sub(string, 1, nchar(string) - 1)),
      TRUE ~ NA_real_
    )
    
    #  [1]   0.80  -0.80  10.45  12.05 -12.05  13.66 -13.66  15.27
    #  [9] -15.27  16.87  18.48 -18.48   2.41  20.09 -20.09  21.70
    # [17]  23.31 -23.31  24.92  26.52  28.13  29.74 -29.74  31.35
    # [25]  32.95 -32.95  34.56 -34.56  36.17  37.78 -37.78  39.38
    # [33]   4.02  -4.02  40.99  42.59  44.20  45.81  49.03   5.63
    # [41]  -5.63  50.63  52.24  55.45  60.27   7.23  -7.23
    

    比来自 BenoitLondon 的正则表达式解决方案要冗长得多,但我倾向于在探索性工作中保持简洁而不是简洁。

    【讨论】:

      【解决方案3】:

      ifelse 的另一种选择可能如下:

      lat <- c("0.80N", "0.80S", "10.45N", "12.05S", "12.05S")
      lat <- as.character(lat)
      ## use of substr function inside an ifelse function
      lat2 <- ifelse(substr(lat,nchar(lat),nchar(lat)) == 'N',
                    as.numeric(substr(lat,1,(nchar(lat)-1))),
                    -as.numeric(substr(lat,1,(nchar(lat)-1))))
      

      【讨论】:

      • 您的答案添加了哪些其他解决方案中不存在的内容?
      • 首先,当我浏览它时,只有一个答案。与第一个答案相比,我的不需要搜索正则表达式。因此对于寻求帮助并且显然不掌握正则表达式的人来说更容易理解。我正在使用简单且广泛使用的函数:ifelsesubstr。此外,它比您的答案更简洁、更简单,这取决于第三方软件包,如 dplyrstringr
      猜你喜欢
      • 2012-01-25
      • 1970-01-01
      • 2015-01-05
      • 1970-01-01
      • 1970-01-01
      • 2019-01-06
      • 2011-03-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多