Как читать данные, когда некоторые числа содержат запятые в качестве разделителя тысяч?

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

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

Ответ 1

Я хочу использовать 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))})

Ответ 2

Не уверен, как правильно 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.

Ответ 3

У вас может быть read.table или read.csv сделать это преобразование для вас полуавтоматически. Сначала создайте новое определение класса, затем создайте функцию преобразования и установите его как метод "как", используя функцию 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'))

Ответ 4

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

В библиотеке/пакете 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. 

Ответ 5

"Препроцесс" в 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'-parameter" ).

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

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

Ответ 6

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 то вы создаете дополнительные ненужные столбцы)

Ответ 7

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

Ответ 8

Я думаю, что предварительная обработка - это путь. Вы можете использовать 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) для чтения файла.

Ответ 9

Очень удобный способ 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

Ответ 10

Другое решение:

 y <- c("1,200","20,000","100","12,111") 

 as.numeric(unlist(lapply( strsplit(y,","),paste, collapse="")))

Он будет значительно медленнее, чем gsub.

Ответ 11

Это не так сложно, попробуйте это: y <- as.numeric(gsub (",", "", as.character(y))), и если это только один из столбцов, вы можете задать для него y $ 2 как показано y $ 2 <- as.numeric(gsub (",", "", as.character(y $ 2)))

Ответ 12

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

locale = locale(decimal_mark = ",")

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

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

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

С уважением

Матеуш Кания