如何读取数据时,一些数字包含逗号作为千位分隔符?
我有一个csv文件,其中一些数值用逗号表示为千位分隔符,例如"1,513"
而不是1513
。 将数据读入R的最简单方法是什么?
我可以使用read.csv(..., colClasses="character")
,但是之后我必须从相关元素中read.csv(..., colClasses="character")
逗号,然后将这些列转换为数字,我找不到一个简单的方法来做到这一点。
不知道如何让read.csv
正确解释它,但是你可以使用gsub
用","
replace","
""
,然后使用as.numeric
将string转换为numeric
:
y <- c("1,200","20,000","100","12,111") as.numeric(gsub(",", "", y)) # [1] 1200 20000 100 12111
这也是R-Help (以及第二季度 )的答案 。
或者,您可以预先处理文件,例如使用unix中的sed
。
你可以让read.table或者read.csv为你做半自动的转换。 首先创build一个新的类定义,然后创build一个转换函数,并使用setAs函数将其设置为“as”方法,如下所示:
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'))
我想使用R,而不是预处理数据,因为在修改数据时它更容易。 按照Shane提出的使用gsub
的build议,我认为这样做可以做的很简单:
x <- read.csv("file.csv",header=TRUE,colClasses="character") col2cvt <- 15:41 x[,col2cvt] <- lapply(x[,col2cvt],function(x){as.numeric(gsub(",", "", x))})
这个问题已经有好几年了,但是我偶然发现了,也许其他人会这么做。
readr
库/包有一些很好的function。 其中之一是解释“杂乱”栏目的好方法,像这样。
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中的“Preprocess”
lines <- "www, rrr, 1,234, ttt \n rrr,zzz, 1,234,567,987, rrr"
可以在textConnection
上使用readLines
。 然后只删除数字之间的逗号:
gsub("([0-9]+)\\,([0-9])", "\\1\\2", lines) ## [1] "www, rrr, 1234, ttt \n rrr,zzz, 1234567987, rrr"
知道但不直接与这个问题直接相关也是有用的,逗号作为十进制分隔符可以通过read.csv2(automagically)或read.table(通过设置“dec”参数)来处理。
编辑:后来我发现了如何通过devise一个新的类来使用colClasses。 看到:
如何在R中加载1000分隔符的df作为数字类?
我认为预处理是要走的路。 您可以使用具有正则expression式replace选项的Notepad ++ 。
例如,如果你的文件是这样的:
"1,234","123","1,234" "234","123","1,234" 123,456,789
然后,您可以使用正则expression式"([0-9]+),([0-9]+)"
并将其replace为\1\2
1234,"123",1234 "234","123",1234 123,456,789
然后你可以使用x <- read.csv(file="x.csv",header=FALSE)
来读取文件。
如果数字用“。”分隔 和小数由“,”(1.200.000,00)在调用gsub
你必须set fixed=TRUE as.numeric(gsub(".","",y,fixed=TRUE))
一个使用mutate_each
和pipe道的dplyr
解决scheme
说你有以下几点:
> 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
并希望从年份variablesX2014-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
将mutate_each
函数内的函数应用于指定的列
我按顺序执行了一个函数(如果你在funs
使用多个函数,那么你创build了额外的不必要的列)
另一个scheme
y <- c("1,200","20,000","100","12,111") as.numeric(unlist(lapply( strsplit(y,","),paste, collapse="")))
不过,它会比gsub
慢得多。
一个非常方便的方法是readr::read_delim
-family。 以这个例子为例: 将多个分隔符的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