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


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

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

12 100

12 ответов:

не уверен, как иметь 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.

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

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

затем бегите читать.csv нравится:

DF <- read.csv('your.file.here', 
   colClasses=c('num.with.commas','factor','character','numeric','num.with.commas'))

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

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

The 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. 

"Препроцесс" в 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 (автоматически) или читать.таблица (с установкой 'dec'-параметра).

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

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

a dplyr решение с помощью mutate_each и труб

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

> 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_each(funs(as.character(.)), X2014:X2016) %>%
    mutate_each(funs(gsub(",", "", .)), X2014:X2016) %>%
    mutate_each(funs(as.numeric(.)), X2014:X2016)

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

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

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

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

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

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

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

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

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

очень удобно 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

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

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

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

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

Это не так сложно, попробуйте это: y

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

locale = locale(decimal_mark = ",")

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

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

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

в отношении

Матеуш Каня