使用write.csv(base R)将数字字段保留为字符

afdcj2ne  于 2022-12-06  发布在  其他
关注(0)|答案(5)|浏览(133)

我有一个data. frame,其中的字符列包含数字(如“0123”、“1234”等)。当我将它们写入csv并读回时,它们最终变成了数字列。write.csvread.csv函数有quote参数,默认情况下,在输出时应该用引号括起字符串,在输入时则遵守它们,因此这种行为是意外的。
如何避免这种情况,而不在重新读入文件时手动指定colClasses
可重现示例:

# dummy data
fake_data <- 
  data.frame(num=1:25, char=letters[1:25], charnum=as.character(1:25),
             stringsAsFactors=F)

# check out col classes - all good
sapply(fake_data, class)

#       num        char     charnum 
# "integer" "character" "character" 

# write it to a file and read it back
fpath <- '~/Desktop/fake_data.csv'
write.csv(fake_data, fpath, row.names=F)
fake_data2 <- read.csv(fpath, stringsAsFactors=F)

# but now look, different classes!
sapply(fake_data2, class)

#       num        char     charnum 
# "integer" "character"   "integer"

错误似乎在读取端,因为文件是用引号写入的。

> cat(readLines(fpath))
"num","char","charnum" 1,"a","1" 2,"b","2" 3,"c","3" 4,"d","4" 5,"e","5" 6,"f","6" 7,"g","7" 8,"h","8" 9,"i","9" 10,"j","10" 11,"k","11" 12,"l","12" 13,"m","13" 14,"n","14" 15,"o","15" 16,"p","16" 17,"q","17" 18,"r","18" 19,"s","19" 20,"t","20" 21,"u","21" 22,"v","22" 23,"w","23" 24,"x","24" 25,"y","25"

会话信息:
R版本3.1.1(2014年7月10日)|平台:x86_64-苹果达尔文13.1.0(64位)

cuxqih21

cuxqih211#

谢谢你的回答。进一步来看,我有以下补充。
选项1:只使用数据。table::fread --按我希望的方式工作
选项2:执行此操作以构造colClasses字符串

# read header and first data line
 first_data_line <- strsplit(readLines(fpath, n=2L)[2], ',')[[1]]

 # find which fields have double quotes
 char_fields <- grep('"', first_data_line)

 # construct colClasses vec
 cc <- rep(NA, length(first_data_line))
 cc[char_fields] <- 'character'

因为我是data.table的粉丝,所以#1可能是我要做的。

yhqotfr8

yhqotfr82#

添加quote=""似乎可以实现您所期望的效果:

sapply( read.csv(fpath, stringsAsFactors=F), class)
sapply( read.csv(fpath, quote="", stringsAsFactors=F), class)
bvn4nwqk

bvn4nwqk3#

您可以使用quote参数来控制read.csv如何处理引号。如果您设置quote="”,则可以在R:

gsub.remove.quotes <- function(x) 
{
      if (is.character(x))
            return(gsub('"$','',gsub('^"','',x)))
      else
            return(x)
}
fake_data2 <- read.csv(fpath, stringsAsFactors=F,quote="")
fake_data3 <- data.frame(lapply(fake_data2,gsub.remove.quotes),stringsAsFactors = F)
sapply(fake_data3, class)

请注意,第二步需要使用引号剥离函数,因为fake_data2中的字符变量实际上包含引号。

jaql4c8m

jaql4c8m4#

这里的讨论很棒,但是对于那些只想把数字作为字符来保存并且需要快速回答的人(比如我)来说,可能会感到困惑。抱歉,我没有注意到问题中的前提条件“没有手动指定colClasses“。但是谷歌也没有,因为这个页面在谷歌搜索的顶部,我不敢相信我花了这么多时间才弄清楚。
正确答案在前面答案的备注部分:read.csv选项中的“除了明确指定colClasses,没有其他方法“。这也是将数字作为字符(或因子)获取的最简单方法。它与write.csv、stringsAsFactors或引号无关。而这个问题详细讨论了colClassesSpecifying colClasses in the read.csv
另一个简单的方法是把原来的数字稍微修改一下,比如把0001修改成_0001。在我的情况下,这样也可以保存麻烦。

dfddblmv

dfddblmv5#

使用data.table进行读写对我来说不起作用。
Write.csv()或data.table::fwrite()将看起来像数字的字符串写为数字。例如,当使用write.csv()或data.table::fwrite()写入字符串“001234”,然后在r中使用read.csv()或data.table::fread()读取该文件(或在Excel中作为csv)时,前一个字符串现在读作“1234”,并且具有类numeric。使用R的原生格式.Rds,保留变量类。等效命令是saveRDS()和readRDS()。希望这对其他人有所帮助。

相关问题