Как читать данные, когда некоторые числа содержат запятые в качестве разделителя тысяч?
У меня есть файл 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.
Это поможет прочитать все числа с запятой как правильные числа.
С уважением
Матеуш Кания