Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
443 views
in Technique[技术] by (71.8m points)

r - Converting 1M to 1000000 elegantly

I want to convert:

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

  cap
1  1B
2 10M
3  2M

to:

      cap
1 1000000000
2   10000000
3    2000000

Here's my solution. It works, but involves adding a column, which I know isn't necessary. What's a better way?

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)
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

We can use gsubfn, match the non-numeric element (\D), replace that with the corresponding value of the list that matches the key, and use eval(parse to convert that to numeric value.

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

We can also use match after extracting the numeric and non-numeric parts, then use match with a vector of letters (c('B', 'M')) to get the numeric index and replace it with new values.

 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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...