Как читать данные, когда некоторые числа содержат запятые в качестве разделителя тысяч? - PullRequest
112 голосов
/ 06 октября 2009

У меня есть CSV-файл, в котором некоторые числовые значения выражены в виде строк с запятыми в качестве разделителя тысяч, например, "1,513" вместо 1513. Какой самый простой способ прочитать данные в R?

Я могу использовать read.csv(..., colClasses="character"), но затем мне нужно вырезать запятые из соответствующих элементов перед преобразованием этих столбцов в числовые, и я не могу найти изящный способ сделать это.

Ответы [ 10 ]

131 голосов
/ 06 октября 2009

Не уверен, как заставить read.csv правильно его интерпретировать, но вы можете использовать gsub для замены "," на "", а затем преобразовать строку в numeric, используя as.numeric:

y <- c("1,200","20,000","100","12,111")
as.numeric(gsub(",", "", y))
# [1]  1200 20000 100 12111

Это был , также ранее ответили на R-Help (и в Q2 здесь ).

Кроме того, вы можете предварительно обработать файл, например, с помощью sed в unix.

55 голосов
/ 31 августа 2010

Вы можете сделать read.table или read.csv сделать это преобразование для вас полуавтоматически. Сначала создайте новое определение класса, затем создайте функцию преобразования и установите его как метод «as», используя функцию setAs следующим образом:

setClass("num.with.commas")
setAs("character", "num.with.commas", 
        function(from) as.numeric(gsub(",", "", from) ) )

Затем запустите read.csv как:

DF <- read.csv('your.file.here', 
   colClasses=c('num.with.commas','factor','character','numeric','num.with.commas'))
16 голосов
/ 06 октября 2009

Я хочу использовать R, а не предварительную обработку данных, поскольку это облегчает процесс пересмотра данных. Следуя предложению Шейна об использовании gsub, я думаю, что это как можно лучше:

x <- read.csv("file.csv",header=TRUE,colClasses="character")
col2cvt <- 15:41
x[,col2cvt] <- lapply(x[,col2cvt],function(x){as.numeric(gsub(",", "", x))})
12 голосов
/ 18 сентября 2015

Этому вопросу уже несколько лет, но я наткнулся на него, а это может означать, что другие будут.

Библиотека / пакет readr имеет несколько приятных особенностей. Один из них - хороший способ интерпретировать «грязные» столбцы, подобные этим.

library(readr)
read_csv("numbers\n800\n\"1,800\"\n\"3500\"\n6.5",
          col_types = list(col_numeric())
        )

Это дает

Источник: локальный фрейм данных [4 x 1]

  numbers
    (dbl)
1   800.0
2  1800.0
3  3500.0
4     6.5

Важный момент при чтении в файлах: вы должны либо предварительно обработать, как в комментарии выше относительно sed, либо вы должны обработать при чтении . Часто, если вы пытаетесь исправить ситуацию после факта, есть некоторые опасные предположения, которые трудно найти. (Именно поэтому плоские файлы так злы.)

Например, если бы я не пометил col_types, я бы получил это:

> read_csv("numbers\n800\n\"1,800\"\n\"3500\"\n6.5")
Source: local data frame [4 x 1]

  numbers
    (chr)
1     800
2   1,800
3    3500
4     6.5

(Обратите внимание, что теперь это chr (character) вместо numeric.)

Или, что более опасно, если бы он был достаточно длинным и большинство ранних элементов не содержали запятых:

> set.seed(1)
> tmp <- as.character(sample(c(1:10), 100, replace=TRUE))
> tmp <- c(tmp, "1,003")
> tmp <- paste(tmp, collapse="\"\n\"")

(так, что последние несколько элементов выглядят так:)

\"5\"\n\"9\"\n\"7\"\n\"1,003"

Тогда вы вообще не сможете прочитать эту запятую!

> tail(read_csv(tmp))
Source: local data frame [6 x 1]

     3"
  (dbl)
1 8.000
2 5.000
3 5.000
4 9.000
5 7.000
6 1.003
Warning message:
1 problems parsing literal data. See problems(...) for more details. 
6 голосов
/ 28 марта 2015

a dplyr решение с использованием mutate_all и труб

скажем, у вас есть следующее:

> dft
Source: local data frame [11 x 5]

   Bureau.Name Account.Code   X2014   X2015   X2016
1       Senate          110 158,000 211,000 186,000
2       Senate          115       0       0       0
3       Senate          123  15,000  71,000  21,000
4       Senate          126   6,000  14,000   8,000
5       Senate          127 110,000 234,000 134,000
6       Senate          128 120,000 159,000 134,000
7       Senate          129       0       0       0
8       Senate          130 368,000 465,000 441,000
9       Senate          132       0       0       0
10      Senate          140       0       0       0
11      Senate          140       0       0       0

и хотите удалить запятые из переменных года X2014-X2016, и преобразовать их в числовые. также, скажем, X2014-X2016 читаются как факторы (по умолчанию)

dft %>%
    mutate_all(funs(as.character(.)), X2014:X2016) %>%
    mutate_all(funs(gsub(",", "", .)), X2014:X2016) %>%
    mutate_all(funs(as.numeric(.)), X2014:X2016)

mutate_all применяет функцию (и) внутри funs к указанным столбцам

Я делал это последовательно, по одной функции за раз (если вы используете несколько функции внутри funs затем вы создаете дополнительные ненужные столбцы)

6 голосов
/ 08 октября 2009

«препроцесс» в R:

lines <- "www, rrr, 1,234, ttt \n rrr,zzz, 1,234,567,987, rrr"

Можно использовать readLines на textConnection. Затем удалите только запятые между цифрами:

gsub("([0-9]+)\\,([0-9])", "\\1\\2", lines)

## [1] "www, rrr, 1234, ttt \n rrr,zzz, 1234567987, rrr"

Также полезно знать, но не имеет прямого отношения к этому вопросу, что запятые как десятичные разделители могут обрабатываться read.csv2 (автоматически) или read.table (с установкой параметра 'dec')

Редактировать: Позже я обнаружил, как использовать colClasses при разработке нового класса. См:

Как загрузить df с разделителем 1000 в R как числовой класс?

4 голосов
/ 07 февраля 2014

Если число отделено "." и десятичные дроби на "," (1.200.000,00) при вызове gsub вы должны set fixed=TRUE as.numeric(gsub(".","",y,fixed=TRUE))

2 голосов
/ 12 мая 2017

Очень удобный способ - readr::read_delim -семейство. Взяв пример отсюда: Импортируя CSV с несколькими разделителями в R , вы можете сделать это следующим образом:

txt <- 'OBJECTID,District_N,ZONE_CODE,COUNT,AREA,SUM
1,Bagamoyo,1,"136,227","8,514,187,500.000000000000000","352,678.813105723350000"
2,Bariadi,2,"88,350","5,521,875,000.000000000000000","526,307.288878142830000"
3,Chunya,3,"483,059","30,191,187,500.000000000000000","352,444.699742995200000"'

require(readr)
read_csv(txt) # = read_delim(txt, delim = ",")

Что приводит к ожидаемому результату:

# A tibble: 3 × 6
  OBJECTID District_N ZONE_CODE  COUNT        AREA      SUM
     <int>      <chr>     <int>  <dbl>       <dbl>    <dbl>
1        1   Bagamoyo         1 136227  8514187500 352678.8
2        2    Bariadi         2  88350  5521875000 526307.3
3        3     Chunya         3 483059 30191187500 352444.7
2 голосов
/ 06 октября 2009

Я думаю, что предварительная обработка - это путь. Вы можете использовать Notepad ++ , у которого есть опция замены регулярного выражения.

Например, если ваш файл был таким:

"1,234","123","1,234"
"234","123","1,234"
123,456,789

Затем вы можете использовать регулярное выражение "([0-9]+),([0-9]+)" и заменить его на \1\2

1234,"123",1234
"234","123",1234
123,456,789

Тогда вы можете использовать x <- read.csv(file="x.csv",header=FALSE) для чтения файла.

0 голосов
/ 20 августа 2018

Используя функцию read_delim, которая является частью библиотеки readr , вы можете указать дополнительный параметр:

locale = locale(decimal_mark = ",")

read_delim("filetoread.csv", ';", locale = locale(decimal_mark = ","))

* Точка с запятой во второй строке означает, что read_delim будет читать значения, разделенные точкой с запятой в формате csv.

Это поможет прочитать все числа с запятой как правильные числа.

Привет

Матеуш Кания

...