Чтение CSV-файла в R с числовым столбцом валюты

Я пытаюсь прочитать в R CSV-файл, содержащий информацию о политических взносах. Насколько я понимаю, столбцы по умолчанию импортируются как факторы, но мне нужно, чтобы столбец суммы («CTRIB_AMT» в наборе данных) был импортирован как числовой столбец, чтобы я мог запускать различные функции, которые не будут работать для факторы. Столбец отформатирован как денежная единица с префиксом "$".

Сначала я использовал простую команду чтения для импорта файла:

contribs <- read.csv('path/to/file')

А затем попытался преобразовать CTRIB_AMT из валюты в числовое:

as.numeric(as.character(sub("$","",contribs$CTRIB_AMT, fixed=TRUE)))

Но это не сработало. Функции, которые я пытаюсь использовать для столбцов CTRIB_AMT:

vals<-sort(unique(dfr$CTRIB_AMT))
sums<-tapply( dfr$CTRIB_AMT, dfr$CTRIB_AMT, sum)
counts<-tapply( dfr$CTRIB_AMT, dfr$CTRIB_AMT, length)

См. соответствующий вопрос здесь.

Любые мысли о том, как импортировать файл изначально, чтобы столбец был числовым, или как преобразовать его после импорта?


person tchaymore    schedule 07.09.2011    source источник
comment
Небольшой пример содержимого файла был бы полезен.   -  person Joshua Ulrich    schedule 07.09.2011
comment
Преобразование sub -> as.character -> as.numeric должно помочь. Что вы имеете в виду под не сработало?   -  person Daniel Dickison    schedule 07.09.2011
comment
Работает на меня. CTRIB_AMT <- factor(c("$5000","$2500","$100")); as.numeric(as.character(sub("$","",CTRIB_AMT, fixed=TRUE)))   -  person Ben Bolker    schedule 07.09.2011


Ответы (5)


Я не уверен, как прочитать его напрямую, но вы можете изменить его, как только он появится:

> A <- read.csv("~/Desktop/data.csv")
> A
  id   desc price
1  0  apple $1.00
2  1 banana $2.25
3  2 grapes $1.97
> A$price <- as.numeric(sub("\\$","", A$price))
> A
  id   desc price
1  0  apple  1.00
2  1 banana  2.25
3  2 grapes  1.97
> str(A)
'data.frame':   3 obs. of  3 variables:
 $ id   : int  0 1 2
 $ desc : Factor w/ 3 levels "apple","banana",..: 1 2 3
 $ price: num  1 2.25 1.97

Я думаю, это мог быть просто пропавший побег на твоей субмарине. $ указывает на конец строки в регулярных выражениях. \$ — это знак доллара. Но тогда вы должны избежать побега...

person Zach    schedule 07.09.2011
comment
Сначала я тоже подумал, что пропал побег, но fixed=TRUE позаботится об этом... - person Ben Bolker; 07.09.2011
comment
+1 Я также нашел gsub( "[$,]", "", . . . полезно для таких фигур, как "$1,234". - person Neil Best; 09.04.2013
comment
Это не должно быть принятым решением; он уступает другим решениям, которые выполняют замену во время чтения, во время чтения возвращают числовое значение и, таким образом, избегают создания множества ненужных и уникальных строк, которые могут тратить Мб/Гб на большой файл, а также медленнее. - person smci; 21.02.2019

Другим способом может быть настройка преобразования с помощью setAs.
Он использовался в двух (похожих) вопросах:

Для ваших нужд:

setClass("Currency")
setAs("character", "Currency",
    function(from) as.numeric(sub("$","",from, fixed=TRUE)))

contribs <- read.csv("path/to/file", colClasses=c(CTRIB_AMT="Currency"))
person Marek    schedule 08.09.2011

Еще одно решение проблемы, решенной давно:

convertCurrency <- function(currency) {
  currency1 <- sub('$','',as.character(currency),fixed=TRUE)
  currency2 <- as.numeric(gsub('\\,','',as.character(currency1))) 
  currency2
}

contribs$CTRIB_AMT_NUM <- convertCurrency(contribs$CTRIB_AMT)
person Anton K    schedule 07.04.2013

Используя преимущества мощных парсеров, предлагаемых пакетом readr из коробки:

my_parser <- function(col) {
  # Try first with parse_number that handles currencies automatically quite well
  res <- suppressWarnings(readr::parse_number(col))
  if (is.null(attr(res, "problems", exact = TRUE))) {
    res
  } else {
    # If parse_number fails, fall back on parse_guess
    readr::parse_guess(col)
    # Alternatively, we could simply return col without further parsing attempt
  }
}

library(dplyr)

name <- c('john','carl', 'hank')
salary <- c('$23,456.33','$45,677.43','$76,234.88')
emp_data <- data.frame(name,salary)

emp_data %>% 
  mutate(foo = "USD13.4",
         bar = "£37") %>% 
  mutate_all(my_parser)

#   name   salary  foo bar
# 1 john 23456.33 13.4  37
# 2 carl 45677.43 13.4  37
# 3 hank 76234.88 13.4  37
person Aurèle    schedule 16.07.2018

Или используйте что-то вроде as.numeric(substr(as.character(contribs$CTRIB_AMT),2,20)), мы знаем, что там точно не будет больше 20 символов.

Еще одна вещь, которую следует отметить, это то, что вы можете полностью исключить необходимость преобразования из коэффициента, если вы установите stringsAsFactors=F в своем вызове на read.csv()

person Brandon Bertelsen    schedule 07.09.2011