R语言 将单位缩写转换为数字

kx5bkwkv  于 2023-10-13  发布在  其他
关注(0)|答案(5)|浏览(154)

我有一个数据集,它在列中显示数值。例如,12M意味着1200万,1.2k意味着1200。M和K是唯一的缩写。我如何编写代码,允许R从最低到最高对这些值进行排序?
我已经考虑过使用gsub将M转换为000,000等,但没有考虑小数(1.5M将是1.5000000)。

llmtgqce

llmtgqce1#

  • 所以你想把国际单位制的缩写('K','M',...)转换成指数,从而转换成数字的十次幂。假设所有单位都是单字母,指数是10**3的均匀间隔幂,下面是处理'Kilo'.'Yotta'和任何未来指数的工作代码:
> 10 ** (3*as.integer(regexpr('T', 'KMGTPEY')))
    [1] 1e+12

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

  • 此外,您可能希望检测和处理未知字母前缀的“不匹配”情况,否则您将得到无意义的-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的滥用),那么你需要特殊情况,例如使用if-else阶梯/表达式(SI单位通常是区分大小写的,'M'意味着'Mega',但'm'严格意味着'milli',即使磁盘驱动器用户另有说法;大写通常用于正指数)。因此,对于一些前缀,@DanielV的特定于大小写的代码更好。
  • 如果你也想要负SI前缀,使用as.integer(regexpr(u, 'zafpnum@KMGTPEY')-8),其中@只是一些一次性字符,以保持均匀的间距,它实际上不应该匹配。同样,如果你需要处理非10**3的幂的单位,如“deci”,“cent”,将需要特殊的 shell ,或一般的基于指令的方法WeNYoBen使用。
  • base::regexpr没有矢量化,而且它在大输入上的性能很差,所以如果你想矢量化并获得更高的性能,请使用stringr::str_locate
ssgvzors

ssgvzors2#

给予这个机会:

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)
    }
}
zpf6vheq

zpf6vheq3#

在这种情况下,您可以使用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
7lrncoxx

7lrncoxx4#

很高兴认识你。
我写了另一个答案

定义函数

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
hlswsv35

hlswsv355#

所有其他答案对我来说都不适合NA(或者产生警告,这也不好)。
这是我的解决方案,它重用了其他解决方案中的一些位。(转载自R data.table speed up SI / Metric Conversion

library(stringr)

si2num <- function(x)
{
  conv <- paste0("e", c(seq(-24 ,-3, by=3), -2, -1, seq(3, 24, by=3),3))
  names(conv) <- c("y","z","a","f","p","n","µ","m","c","d","K","M","G","T","P","E","Z","Y","k")
  
  xout <- str_replace_all(x, conv)
  xout <- as.numeric(xout)
  
  return(xout)
}

x <- c(NA,"10", "10.01K",NA,"10.1M", "20K", "21k",NA)

si2num(x)
[1]       NA       10    10010       NA 10100000    20000    21000       NA

相关问题