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

Rob*_*man 114 csv r r-faq

我有一个csv文件,其中一些数值表示为字符串,逗号为千分隔符,例如,"1,513"而不是1513.将数据读入R的最简单方法是什么?

我可以使用read.csv(..., colClasses="character"),但是在将这些列转换为数字之前,我必须从相关元素中删除逗号,我找不到一个巧妙的方法来做到这一点.

Sha*_*ane 136

不知道如何拥有read.csv正确解释它,但你可以使用gsub,以取代",""",然后将字符串转换为numeric使用as.numeric:

y <- c("1,200","20,000","100","12,111")
as.numeric(gsub(",", "", y))
# [1]  1200 20000 100 12111
Run Code Online (Sandbox Code Playgroud)

之前在R-Help(以及第二季度)中也回答过这个问题.

或者,您可以预处理文件,例如使用sedunix.


Gre*_*now 55

您可以半自动read.table或read.csv为您执行此转换.首先创建一个新的类定义,然后创建一个转换函数,并使用setAs函数将其设置为"as"方法,如下所示:

setClass("num.with.commas")
setAs("character", "num.with.commas", 
        function(from) as.numeric(gsub(",", "", from) ) )
Run Code Online (Sandbox Code Playgroud)

然后运行read.csv,如:

DF <- read.csv('your.file.here', 
   colClasses=c('num.with.commas','factor','character','numeric','num.with.commas'))
Run Code Online (Sandbox Code Playgroud)

  • 这是一个非常好的技巧.它可以用于导入转换(例如使用`setAs("character","logical.YN",函数(from)c(Y = TRUE,N = FALSE)将Y/N值转换为逻辑向量[来自] ])`). (3认同)

Rob*_*man 16

我想使用R而不是预处理数据,因为它在修改数据时更容易.根据Shane的使用建议gsub,我认为这与我能做的一样整洁:

x <- read.csv("file.csv",header=TRUE,colClasses="character")
col2cvt <- 15:41
x[,col2cvt] <- lapply(x[,col2cvt],function(x){as.numeric(gsub(",", "", x))})
Run Code Online (Sandbox Code Playgroud)


Mik*_*son 14

这个问题已有几年了,但我偶然发现了,这意味着其他人也会这样.

readr库/包有一些不错的功能吧.其中一个是解释"凌乱"列的好方法,就像这些.

library(readr)
read_csv("numbers\n800\n\"1,800\"\n\"3500\"\n6.5",
          col_types = list(col_numeric())
        )
Run Code Online (Sandbox Code Playgroud)

这产生了

来源:本地数据框[4 x 1]

  numbers
    (dbl)
1   800.0
2  1800.0
3  3500.0
4     6.5
Run Code Online (Sandbox Code Playgroud)

阅读文件时要注意的重点是:您必须预先处理,如上面的评论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
Run Code Online (Sandbox Code Playgroud)

(注意它现在是chr(character)而不是a numeric.)

或者,更危险的是,如果它足够长并且大多数早期元素不包含逗号:

> set.seed(1)
> tmp <- as.character(sample(c(1:10), 100, replace=TRUE))
> tmp <- c(tmp, "1,003")
> tmp <- paste(tmp, collapse="\"\n\"")
Run Code Online (Sandbox Code Playgroud)

(这样最后几个元素看起来像:)

\"5\"\n\"9\"\n\"7\"\n\"1,003"
Run Code Online (Sandbox Code Playgroud)

然后你会发现读这个逗号的麻烦了!

> 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. 
Run Code Online (Sandbox Code Playgroud)


Pau*_*aul 7

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
Run Code Online (Sandbox Code Playgroud)

并希望从年变量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)
Run Code Online (Sandbox Code Playgroud)

mutate_all将函数应用于funs指定的列

我按顺序执行,一次执行一个函数(如果你在里面使用多个函数,funs那么你创建了额外的,不必要的列)

  • `mutate_each`已被弃用.你想用`mutate_at`或类似的方式更新你的答案吗? (3认同)

42-*_*42- 6

R中的"预处理":

lines <- "www, rrr, 1,234, ttt \n rrr,zzz, 1,234,567,987, rrr"
Run Code Online (Sandbox Code Playgroud)

可以用readLinestextConnection.然后只删除数字之间的逗号:

gsub("([0-9]+)\\,([0-9])", "\\1\\2", lines)

## [1] "www, rrr, 1234, ttt \n rrr,zzz, 1234567987, rrr"
Run Code Online (Sandbox Code Playgroud)

知道但不直接与此问题相关的是有用的是,逗号作为小数分隔符可以由read.csv2(自动)或read.table(设置'dec'参数)来处理.

编辑:后来我发现了如何通过设计一个新类来使用colClasses.看到:

如何在R中使用1000分隔符加载df作为数字类?


小智 6

使用 read_delim 函数( readr库的一部分),您可以指定附加参数:

locale = locale(decimal_mark = ",")

read_delim("filetoread.csv", ";", locale = locale(decimal_mark = ","))
Run Code Online (Sandbox Code Playgroud)

*第二行中的分号表示 read_delim 将读取 csv 分号分隔值。

这将有助于将所有带逗号的数字读取为正确的数字。

问候

马特乌斯·卡尼亚


Ron*_*hah 6

我们也可以使用readr::parse_number,但列必须是字符。如果我们想将它应用于多列,我们可以使用lapply

df[2:3] <- lapply(df[2:3], readr::parse_number)
df

#  a        b        c
#1 a    12234       12
#2 b      123  1234123
#3 c     1234     1234
#4 d 13456234    15342
#5 e    12312 12334512
Run Code Online (Sandbox Code Playgroud)

或者使用mutate_atfromdplyr将其应用于特定变量。

library(dplyr)
df %>% mutate_at(2:3, readr::parse_number)
#Or
df %>% mutate_at(vars(b:c), readr::parse_number)
Run Code Online (Sandbox Code Playgroud)

数据

df <- data.frame(a = letters[1:5], 
                 b = c("12,234", "123", "1,234", "13,456,234", "123,12"),
                 c = c("12", "1,234,123","1234", "15,342", "123,345,12"), 
                 stringsAsFactors = FALSE)
Run Code Online (Sandbox Code Playgroud)