从十亿转为百万,反之亦然

时间:2016-06-24 12:13:54

标签: r dataframe

假设我有以下名为DF的数据框。我想将Revenue列中的所有值转换为相同的单位。

Brands   Revenue
A        50.1 bn
B        41.2 bn
C        32.5 Mn
D        15.1 bn

请注意,bnMn是向量的一部分。

6 个答案:

答案 0 :(得分:8)

一个想法,

new <- ifelse(gsub('.*\\s+', '', DF$Revenue) == 'bn',
              as.numeric(gsub('[A-Za-z]', '', DF$Revenue))*1000, DF$Revenue)

new[!grepl('Mn', new)] <- paste(new[!grepl('Mn', new)], 'Mn', sep = ' ')
DF$Revenue <- new

DF
#  Brands  Revenue
#1      A 50100 Mn
#2      B 41200 Mn
#3      C  32.5 Mn
#4      D 15100 Mn

然后做相反的事,

new <- ifelse(gsub('.*\\s+', '', DF$Revenue) == 'Mn',
               as.numeric(gsub('[A-Za-z]', '', DF$Revenue))/1000, DF$Revenue)

 new[!grepl('bn', new)] <- paste(new[!grepl('bn', new)], 'bn', sep = ' ')
 DF$Revenue <- new
 DF
#  Brands   Revenue
#1      A   50.1 bn
#2      B   41.2 bn
#3      C 0.0325 bn
#4      D   15.1 bn

答案 1 :(得分:4)

另一种方法:使用split

将货币值与文本分开
# split value and "level" in a list
temp <- split(df$Revenue, split=" ")
# add separately to data.frame
df$Revenue <- sapply(temp, function(i) as.numeric(i[[1]]))
df$level <- sapply(temp, function(i) "[", 2)

df
  Brands Revenue level
1      A 50100.0    bn
2      B 41200.0    bn
3      C    32.5    bn
4      D 15100.0    bn

现在,使用&#34; bn&#34;:

转换为数百万个子集
df$Revenue[df$level == "bn"] <- df$Revenue[df$level == "bn"] * 1000
df$level <- "Mn"

这导致

df
  Brands Revenue level
1      A  0.0501    Mn
2      B  0.0412    Mn
3      C 32.5000    Mn
4      D  0.0151    Mn

而是转换为数十亿(类似的程序)

df$Revenue[df$level == "Mn"] <- df$Revenue[df$level == "Mn"] / 1000
df$level <- "bn"

这导致

df
  Brands Revenue level
1      A  0.0501    bn
2      B  0.0412    bn
3      C 32.5000    bn
4      D  0.0151    bn

答案 2 :(得分:4)

与先前的解决方案相比,可能简化解析过程。 我正在使用令人敬畏的库stringr

library(stringr)

dd$units <- word(dd$Revenue, 2, sep = " ")
dd$amounts <- word(dd$Revenue, 1, sep = " ")


# The following lines create an extra column in the dataframe,
# You can overwrite the original column if you so wish.

# Convert to billions
dd$convert_to_bn <- paste(as.numeric(dd$amounts) * ifelse(dd$units == "bn", 1 , 0.001), "bn")

# Convert to millions
dd$convert_to_mn <- paste(as.numeric(dd$amounts) * ifelse(dd$units == "Mn", 1 , 1000), "Mn")

答案 3 :(得分:3)

这是一个替代&#34;单位&#34;的解决方案。通过适当的因素并评估最终的计算结果。

第一步是替换&#34; bn&#34;和&#34; Mn&#34;由一个因素:

conversion <- c(Mn = 1/1000, bn = 1)
for (unit in names(conversion)) {
  df$Revenue <- gsub(unit, paste0("*", conversion[unit]), df$Revenue)
}
df
##   CBrands             Revenue
## 1       A             50.1 *1
## 2       B             41.2 *1
## 3       C         32.5 *0.001
## 4       D             15.1 *1

然后评估Revenue和&#34; bn&#34;中的表达式再次:

df$Revenue <- sapply(df$Revenue, function(x) eval(parse(text = x)))
df$Revenue <- paste(df$Revenue, "bn")
df
##   CBrands   Revenue
## 1       A   50.1 bn
## 2       B   41.2 bn
## 3       C 0.0325 bn
## 4       D   15.1 bn

答案 4 :(得分:1)

我们也可以使用gsubfn执行此操作。将'bn','Mn'替换为* 1* 1/1000,评估字符串并粘贴'bn'。

library(gsubfn)
sprintf("%.2f bn", sapply(gsubfn("([[:alpha:]]+)", list(Mn = "* 1/1000", 
        bn = "* 1"), df1$Revenue), function(x) eval(parse(text=x))))
#[1] "50.10 bn" "41.20 bn" "0.03 bn"  "15.10 bn"

答案 5 :(得分:0)

您应该考虑是否确实希望将收入存储为数据中的文本。这将使得对收入进行任何类型的计算变得更加困难。您可能会发现将收入存储为浮点数并编写自定义格式以使用后缀显示它更好。衡量单位可以是1,数十亿或其他任何东西。

根据您的决定,以下是使用流行的“tidyverse”软件包的两种方法。在这两种方法中,使用tidyr的separate(..., sep='\\s',convert=TRUE)将您的收入文本拆分为数字和单位。

将收入保存为文本(不是最佳做法)

library(tidyr)
library(dplyr)
DF %>% 
  separate(Revenue, into=c('Rev.Amt','Rev.Denom'), sep='\\s', convert=TRUE) %>%
  mutate( Rev.Amt = Rev.Amt/ifelse(Rev.Denom=='Mn',1000,1), # other conversions as needed
          Rev.Denom = 'bn' ) %>%
  unite(Revenue, Rev.Amt, Rev.Denom, sep=' ')
# Brands   Revenue
# 1      A   50.1 bn
# 2      B   41.2 bn
# 3      C 0.0325 bn
# 4      D   15.1 bn

将收入存储为数字(更好的做法)

在这里,我们将收入存储为没有倍数的单位,但您也可以将其存储为数十亿,并避免显示分割步骤。

DF %<>% 
  separate(Revenue, into=c('Rev.Amt','Rev.Denom'), sep='\\s', convert=TRUE) %>%
  mutate( Rev.Amt = Rev.Amt*ifelse(Rev.Denom=='Mn', 1e6, 1e9)) %>% # other conv as needed
  select(-Rev.Denom)

# To display numeric revenue in billions
showInBn <- function(x) paste(x/1e9,'bn')
DF %>% mutate(Rev.Expr = showInBn(Rev.Amt)) %>% select(-Rev.Amt)
#   Brands  Rev.Expr
# 1      A   50.1 bn
# 2      B   41.2 bn
# 3      C 0.0325 bn
# 4      D   15.1 bn