【问题标题】:Converting unit abbreviations to numbers将单位缩写转换为数字
【发布时间】:2019-10-03 04:11:29
【问题描述】:

我有一个数据集,它对列中的数值进行缩写。例如,12M 表示 1200 万,1.2k 表示 1200。 M 和 k 是唯一的缩写。如何编写允许 R 将这些值从最低到最高排序的代码?

我曾考虑使用 gsub 将 M 转换为 000,000 等,但这并未考虑小数(1.5M 将是 1.5000000)。

【问题讨论】:

  • 如果它安装在您的系统和路径中,您可以从system() 调用numfmt。类似于system(paste("numfmt --from=auto --to=none", "12M"), intern = TRUE)
  • 相关先前讨论 - stackoverflow.com/questions/36806215/… 包括解决此问题的 cmets 中的答案。
  • 另外,在您的情况下,我们似乎可以安全地假设尾数标准化(例如,12.00k0.012k 未标准化)
  • 哦,您是否关心处理NANaNInf 而不会炸毁?

标签: r units-of-measurement exponent


【解决方案1】:

试一试:

Text_Num <- function(x){
    if (grepl("M", x, ignore.case = TRUE)) {
        as.numeric(gsub("M", "", x, ignore.case = TRUE)) * 1e6
    } else if (grepl("k", x, ignore.case = TRUE)) {
        as.numeric(gsub("k", "", x, ignore.case = TRUE)) * 1e3
    } else {
        as.numeric(x)
    }
}

【讨论】:

  • 这正是我正在寻找的那种代码,我没有想到在更改为数值后进行乘法运算。唯一的问题是它在达到“k”值时返回“NA”。我正在想办法解决
【解决方案2】:

在您的情况下,您可以使用gsubfn

a=c('12M','1.2k')
dict<-list("k" = "e3", "M" = "e6")
as.numeric(gsubfn::gsubfn(paste(names(dict),collapse="|"),dict,a))
[1] 1.2e+07 1.2e+03

【讨论】:

    【解决方案3】:
    • 因此,您想将 SI 单位缩写('K'、'M'、...)转换为指数,从而转换为十的数字幂。 鉴于所有单位都是单字母,并且指数是 10**3 的均匀间隔幂,下面是处理“Kilo”...“Yotta”以及任何未来指数的工作代码:
        > 10 ** (3*as.integer(regexpr('T', 'KMGTPEY')))
        [1] 1e+12
    

    然后将十的幂乘以你所拥有的十进制值。

    • 另外,您可能希望检测和处理未知字母前缀的“不匹配”情况,否则您会得到一个无意义的-1*3
        > unit_to_power <- function(u) {
            exp_ <- 10**(as.integer(regexpr(u, 'KMGTPEY')) *3)
            return (if(exp_>=0) exp_ else 1)
        }
    
    • 现在,如果您想将“k”和“K”都与 Kilo 进行不区分大小写匹配(就像计算机人经常写的那样,即使从技术上讲这是对 SI 的滥用),那么您需要特别-case 例如 if-else 梯形图/表达式(SI 单位通常区分大小写,“M”表示“Mega”,但“m”严格表示“milli”,即使磁盘驱动器用户另有说明;大写通常是对于正指数)。所以对于一些前缀,@DanielV 的 case-specific 代码更好。

    • 1234563同样,如果您需要处理 'deci'、'centi' 等非 10**3 次方单位,则需要特殊大小写或 WeNYoBen 使用的基于 dict 的一般方法。
    • base::regexpr 没有矢量化,而且它在大输入上的性能也很差,所以如果你想矢量化并获得更高的性能,请使用stringr::str_locate

    【讨论】:

      【解决方案4】:

      很高兴认识你。

      我写了另一个答案

      定义函数

      res = function (x) {
        result = as.numeric(x)
        if(is.na(result)){
        text = gsub("k", "*1e3", x, ignore.case = T)
        text = gsub("m", "*1e6", text, ignore.case = T)
        result = eval(parse(text = text))
        } 
        return(result)
      }
      

      结果

      > res("5M")
      [1] 5e+06
      > res("4K")
      [1] 4000
      > res("100")
      [1] 100
      > res("4k")
      [1] 4000
      > res("1e3")
      [1] 1000
      

      【讨论】:

        猜你喜欢
        • 2014-03-30
        • 2020-02-19
        • 1970-01-01
        • 1970-01-01
        • 2022-01-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多