优雅地将1M转换为1000000

RyG*_*Guy 2 r data.table

我想转换:

library(data.table)
market.cap <- data.table(cap=c("1B", "10M", "2M"))

  cap
1  1B
2 10M
3  2M
Run Code Online (Sandbox Code Playgroud)

至:

      cap
1 1000000000
2   10000000
3    2000000
Run Code Online (Sandbox Code Playgroud)

这是我的解决方案.它有效,但涉及添加一个列,我知道这不是必需的.什么是更好的方式?

market.cap[, cap1 := cap]
market.cap$cap = sapply(market.cap$cap, function(x) (as.numeric(temp <- gsub("B", "", x)) * 1000000000))
market.cap$cap1 = sapply(market.cap$cap1, function(x) (as.numeric(temp <- gsub("M", "", x)) * 1000000))
M = data.frame(x = na.omit(market.cap$cap))
B = data.frame(x = na.omit(market.cap$cap1))
rbind(M,B)
Run Code Online (Sandbox Code Playgroud)

akr*_*run 6

我们可以使用gsubfn,匹配非数字元素(\\D),将其替换valuelist匹配的相应元素key,并用于eval(parse将其转换为数值.

library(gsubfn) 
options(scipen=999)
unname(sapply(gsubfn('\\D', list(B= '*1e9', M= '*1e6'), 
       market.cap$cap), function(x) eval(parse(text=x))))
#[1] 1000000000   10000000    2000000
Run Code Online (Sandbox Code Playgroud)

我们也可以match在提取numeric非数字部分后使用,然后使用matchletters(c('B', 'M'))向量来获取数字索引并用新值替换它.

 market.cap[,  cap1 := as.numeric(sub('\\D', '', 
    cap))*c(1e9, 1e6)[match( sub('\\d+', '', cap), c('B', 'M'))]]
 #    cap       cap1
 #1:  1B 1000000000
 #2: 10M   10000000
 #3:  2M    2000000
Run Code Online (Sandbox Code Playgroud)