如何读取数据时,一些数字包含逗号作为千位分隔符?

我有一个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 

(请注意,它现在是一个chrcharacter ),而不是一个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_eachmutate_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