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

时间:2014-10-20 17:29:37

标签: r read.table line-endings

摘要

我尝试用read.table阅读推文数据。但是我的行仅在\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 
(:

这看起来在错误的地方只有一个换行符!那现在是一个很大的问题,我怎么能说一条线是新线呢?为什么会那样?我决定使用&#34;显示所有字符&#34;然后找出更详细的外观(再次添加空格,现在你看到我更准确地发布格式了)。 Notepad ++中的选项条目的真实外观如下:

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

注意笑脸前面的CR

简单的解决方案

我以某种方式&#34;解决了#34;通过在第一列中读取字符,填充行并将空字段设置为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?

OS /文件/等

根据评论中的要求,我们提供了更多技术信息:

  • $ platform:&#34; x86_64-w64-mingw32&#34;
  • $ system:&#34; x86_64,mingw32&#34;
  • $ svn rev:&#34; 66115&#34;
  • $ version.string:&#34; R版本3.1.1(2014-07-10)&#34;
  • 操作系统:Windows 8(我没想到R会在我的mingw安装下运行)

示例文件:

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

1 个答案:

答案 0 :(得分:2)

由于R在多个操作系统上运行,并且不同的操作系统使用不同的行结尾,因此很难精确控制用作所有操作系统的行结尾的内容。解决这个问题的最简单方法是将tweet列包装在引号中。当您有引用字段时,允许嵌入的换行符。否则,您可以使用正则表达式等操作字节。这完全取决于您打算如何处理嵌入式换行符。不确定是否要保留它们。

这是您的示例文件转储

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)

如果您想先进行其他操作,这可能会有所帮助。例如,您可能希望删除\r之后没有的\n值。你可以用

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

我想你可以直接读到read.table

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

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