R: read.table 将\r 解释为新行

标签 r read.table line-endings

摘要

我尝试使用 read.table 读取 Twitter 数据。但我的行仅在 \r 中终止,这会导致问题,所以我想跳过一些行。

数据格式

数据采用制表符分隔的 csv 格式,格式如下:

id \t userid \t date \t latitude \t longitude \t location \t tweet \r\n

(注意:为了可读性,我添加了空格,\t\r\n 是预期的 TAB、CR 和 LF )

一些例子是:

488397447040086017  1220042672  20140713190000  -22.923528  -43.238966  Rio de Janeiro, Rio de Janeiro  os moradores da minha rua devem me odiar
488397446960381952  1960969112  20140713190000  60.998575   68.998468   Ханты-Мансийск, Ханты-Мансийск  Вот интересом, мне одной пофиг на футбол?
488397446997762049  1449959828  20140713190000  32.777693   -97.307257  Fort Worth, TX  Buena suerte Argentina

读入数据

有一些问题(# 作为注释,' 作为引号字符、编码,...),我已经部分解决了:

readTweets <- function(fileName) {
  # read tweets from file
  tweets <- read.table(fileName, sep = "\t", quote = "", comment.char = "",
                       col.names = c("id", "user", "date", "latitude", 
                                     "longitude", "location", "tweet"),
                       colClasses = c("numeric", "numeric", "character",
                                      "double", "double", "character",
                                      "character"), encoding = "utf8")

  tweets
}

正如您可以轻松看到的,我还添加了 colClasses 参数,为字段提供一些有用的类型(我还将日期列更改为 POSIXct,但我必须这样做我自己的格式化 - 侧面任务:有没有办法自动将函数应用于导入的列?)。

错误

这适用于像上面给出的小型测试集。但是,当我尝试加载更大的数据集时,出现以下错误:

Error in scan(file, what, nmax, sep, dec, quote, skip, nlines, na.strings,  : 
  scan() expected 'a real', got '(:'

稍微搜索一下该文件就会显示以下条目:

488397464438071297  403662206   20140713190004  19.320504   -76.426316      @Toneishe_Lovee @purifiedhoran 
(:

这看起来只是换行符出现在错误的位置!现在这是一个大问题,我怎么能说一条线是不是一条新线呢?为什么会这样呢?我决定进行更详细的查看,并使用 Notepad++ 中的“显示所有字符”选项发现(再次添加空格,现在您知道为什么我更准确地发布了格式)条目的实际外观:

488397464438071297 \t 403662206 \t 20140713190004 \t 19.320504 \t -76.426316 \t @Toneishe_Lovee @purifiedhoran \r (: \r\n

注意笑脸前面的CR

简单的解决方案

我以某种方式“解决”了这个问题,方法是在第一列中读取字符,填充行并将空字段设置为NA,然后使用complete.cases:

readTweets <- function(fileName) {
  # read tweets from file
  tweets <- read.table(fileName, sep = "\t", quote = "", comment.char = "",
                       col.names = c("id", "user", "date", "latitude", 
                                     "longitude", "location", "tweet"),
                       colClasses = c("character", "numeric", "character",
                                      "double", "double", "character",
                                      "character"), encoding = "utf8",
                       fill = TRUE, na.strings = TRUE)
  # remove incorrect rows and convert id to numeric
  tweets      <- tweets[complete.cases(tweets[,c("id", "user", "date")]),]
  tweets$id   <- as.numeric(tweets$id)
  rownames(tweets) <- NULL
  tweets
}

我仍然想知道是否可以在 Twitter 中输入 CR,或者给我 csv 文件的人只是搞乱了格式。

专业的解决方案

是否可以跳过非整行(无需再次处理所有数据),以便我可以直接使用 colClass 数字作为 ID?

操作系统/文件/等

根据此处评论中的要求,提供更多技术信息:

  • $平台:“x86_64-w64-mingw32”
  • $系统:“x86_64,mingw32”
  • $svn 版本:“66115”
  • $version.string: "R 版本 3.1.1 (2014-07-10)"
  • 操作系统:Windows 8(我没想到 R 会与我安装的 mingw 一起运行)

示例文件:

  • Download , 788 B,csv(制表符分隔),包含 5 条推文,其中包括错误的一条(第二条)
  • 文件格式为UTF-8无BOM,Notepad++将行结尾识别为Dos\Windows

最佳答案

由于 R 在多个操作系统上运行,并且不同的操作系统使用不同的行结束符,因此很难准确控制使用什么作为适用于所有操作系统的行结束符。解决此问题的最简单方法是将推文列用引号引起来。当您有带引号的字段时,允许嵌入换行符。否则,您可以使用正则表达式等操作字节。这完全取决于您打算如何处理嵌入的换行符。不确定您是否想保留它们。

这是示例文件的转储

ctx <- "488397464357974017\t2168124983\t20140713190004\t24.584653\t46.540044\tالرياض, المملكة العربية السعودية\tأتوقع البطولة أرجنتينية ، من بداية البطولة كل الظروف والعوامل تريد الأرجنتين ..\r\n488397464438071297\t403662206\t20140713190004\t19.320504\t-76.426316\t\t@Toneishe_Lovee @purifiedhoran \r(:\r\n488397464442265600\t2510306157\t20140713190004\t36.517741\t-5.317234\tGaucín, Málaga\t#AlemaniaArgentina Vamos #GER\r\n488397464584871936\t539048975\t20140713190004\t42.550627\t9.440454\tLucciana, Haute-Corse\ton a tous le seum contre Pauline 4/5 mais dsl zayn l'a pas unfollow , ça fait 5 mois que vous sortez ça \U0001f615\r\n488397463997276160\t194876164\t20140713190004\t37.724866\t-120.93389\tRiverbank, CA\t@AlexxisAvila Shhh! Lol\r\n"

我们可以将它分成一个字符矩阵

mm <- do.call(rbind, strsplit(strsplit(ctx, "\r\n")[[1]], "\t"))

然后我们可以转换为data.frame

dd<-data.frame(mm, stringsAsFactors=F)
dd[,c(1,2,4,5)]<-lapply(dd[,c(1,2,4,5)], as.numeric)

然后,如果您将其写入文件(并允许引用字符值)

write.table(dd, "tweets2.csv", row.names=F, col.names=F, sep="\t")

您可以毫无问题地读回它

dd2 <- read.table("tweets2.csv", sep = "\t", comment.char = "",
    col.names = c("id", "user", "date", "latitude", 
        "longitude", "location", "tweet"),
    colClasses = c("character", "numeric", "character",
        "double", "double", "character",
         "character"),
    encoding = "utf8")

因此,如果您收到的文件在最后一列周围带有引号,则导入它会容易得多。

如果您想像我创建 ctx 那样将文件作为一个大字符串读取,您可以使用

ctx <- readChar(fileName, file.info(fileName)$size)

如果您想先进行其他操作,这可能会有所帮助。例如,您可能想要删除后面不跟有 \n\r 值。你可以做什么

gsub("\\r(?!\\n)","[nl]", ctx, perl=T)

我认为你可以直接将其读入 read.table

read.table(text=gsub("\\r(?!\\n)","[nl]", ctx, perl=T), sep="\t")

(我正在 Mac 上进行测试,它使用不同的行结尾,因此它不起作用,但在 Windows 上可能有效)。

关于R: read.table 将\r 解释为新行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26471458/

相关文章:

python - 为什么 Python 2.7.3 认为我的 .csv 文件都在一行上?

string - 访问R中str_split分割的各个值,找到最后一个?

r - 如何仅使用 ggplot2 命令将 "break"连续变量转换为离散区间

read.table() 在 R 中将数值读取为整数

r - 从 R 中的表读取自定义日期时间时出错

将 PISA 数据读入 R - read.table 错误

svn - 如何避免 svn 存储库中的混合 eol 样式

r - 在 R 中解码 URL 字符串向量

r - 使用 R 中的人口比率和最小/最大标准将值分配给区域

javascript - 预期换行符为 'LF' 但发现 'CRLF' 换行符样式