摘要
我尝试使用 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/