Answers:
您可以让read.table或read.csv半自动为您完成此转换。首先创建一个新的类定义,然后创建一个转换函数,并使用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的use的建议gsub
,我认为这差不多可以做到:
x <- read.csv("file.csv",header=TRUE,colClasses="character")
col2cvt <- 15:41
x[,col2cvt] <- lapply(x[,col2cvt],function(x){as.numeric(gsub(",", "", x))})
这个问题已经有好几年了,但我偶然发现了,这意味着其他人可能会这样。
该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.
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
则会创建其他不必要的列)
mutate_each
不推荐使用。您想使用mutate_at
或类似的方式更新您的答案吗?
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'参数的设置)处理,这也很有用。
编辑:后来我发现如何通过设计一个新类使用colClasses。看到:
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
使用readr 库的一部分read_delim函数,可以指定其他参数:
locale = locale(decimal_mark = ",")
read_delim("filetoread.csv", ';", locale = locale(decimal_mark = ","))
*第二行中的分号表示read_delim将读取csv分号分隔的值。
这将有助于读取所有带逗号的数字作为正确的数字。
问候
马特乌斯·卡尼亚(Mateusz Kania)
我们也可以使用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
或使用mutate_at
from dplyr
将其应用于特定变量。
library(dplyr)
df %>% mutate_at(2:3, readr::parse_number)
#Or
df %>% mutate_at(vars(b:c), readr::parse_number)
数据
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)
我认为预处理是要走的路。您可以使用具有正则表达式替换选项的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)
来读取文件。
setAs("character", "logical.Y.N", function(from) c(Y=TRUE,N=FALSE)[from] )
)。