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

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

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

12 ответов

Решение

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

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

Вы можете сделать 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'))

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

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. 

Мы также можем использовать readr::parse_number, однако столбцы должны быть символами. Если мы хотим применить его для нескольких столбцов, мы можем перебирать столбцы, используяlapply

df[2:3] <- lapply(df[2:3], readr::parse_number)
df

#  a        b        c
#1 a    12234       12
#2 b      123  1234123
#3 c     1234     1234
#4 d 13456234    15342
#5 e    12312 12334512

Или используйте mutate_at из dplyr применить его к конкретным переменным.

library(dplyr)
df %>% mutate_at(2:3, readr::parse_number)
#Or
df %>% mutate_at(vars(b:c), readr::parse_number)

данные

df <- data.frame(a = letters[1:5], 
                 b = c("12,234", "123", "1,234", "13,456,234", "123,12"),
                 c = c("12", "1,234,123","1234", "15,342", "123,345,12"), 
                 stringsAsFactors = FALSE)

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

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

locale = locale(decimal_mark = ",")

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

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

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

С уважением

Матеуш Кания

"Препроцесс" в 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 как числовой класс?

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

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

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

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

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

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

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

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

Другие вопросы по тегам