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