Как читать данные, когда некоторые числа содержат запятые в качестве разделителя тысяч?
у меня есть csv-файл, где некоторые числовые значения выражаются в виде строк с запятыми в качестве разделителя тысяч, например "1,513"
вместо 1513
. Каков самый простой способ считывания данных в R?
Я могу использовать read.csv(..., colClasses="character")
, но тогда я должен удалить запятые из соответствующих элементов перед преобразованием этих столбцов в числовые, и я не могу найти аккуратный способ сделать это.
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
,хотя.
С помощью функции read_delim, которая является частью readr библиотека, вы можете указать дополнительный параметр:
locale = locale(decimal_mark = ",") read_delim("filetoread.csv", ';", locale = locale(decimal_mark = ","))
*точка с запятой во второй строке означает, что read_delim будет читать csv разделенные точкой с запятой значения.
Это поможет прочитать все числа с запятой как правильные числа.
в отношении
Матеуш Каня