Re: [问题] read.table 多个sep 遗失值miss

楼主: celestialgod (天)   2016-05-01 02:16:08
※ 引述《f496328mm (为什么会流泪)》之铭言:
: 问题一
: 我要读的是笔记本txt档
: 档案太大无法先用excel处理
: 我的分隔符号有多个 请问要怎么写??
: 我的code
: read.table("d:\\xxx.txt" ,sep=";", fill=T, quote="")
: 我想要用 ; 和 空格 当作分隔符号 未来可能再增加
假设你资料长这样,可以先用regex把分隔符号抓出来,再用fread处理:
sam 18; boy
paul; 20 boy
charlotte; 21; girl
christy 17 girl
好读版:http://pastebin.com/QjwNiyNK
备注很长,不想看就转下一页吧,无所谓的murmur XD
(备注:library后面注解是该套件会用到的函数,我尽量减少使用奇怪的函数,
%>>%部分,我这里用法几乎都跟%>%一样,去看magrittr介绍即可,
有兴趣了解更多,再到作者网站看,%>>%多了不少好用的功能,
data.table主要是用fread,data.table跟setnames都可以分别用
data.frame, `names<-`这两个函数取代,rlply可以用replicate取代
mutate也可以用base的transform取代,str_c跟paste一样,
str_replace_all只是把gsub原本放字串的位置移到第一个,方便pipe,
还有其他问题或是不会取代函数的话,再推文或是回文发问吧,
至于为什么要用其他函数,其函数有其他好处加上习惯,甚至只是因为style问题,
就不在程式中做取代了)
code:
library(data.table) # fread, data.table, setnames
library(pipeR) # %>>%
library(plyr) # rlply
library(dplyr) # mutate
library(stringr) # str_replace_all, str_c
readLines(textConnection('sam 18; boy
paul; 20 boy
charlotte; 21; girl
christy 17 girl')) %>>%
str_replace_all("([a-zA-Z0-9]);? ", "\\1,") %>>%
# str_replace_all比gsub适合用在pipeR
str_c(collapse = "\n") %>>% fread %>>% # str_c = paste
setnames(c("name", "age", "sex")) %>>%
mutate(age = as.integer(age))
# name age sex
# 1 sam 18 boy
# 2 paul 20 boy
# 3 charlotte 21 girl
# 4 christy 17 girl
用两百万个row测试看看:
# data generation
textData <- raply(5e5, 'sam 18; boy
paul; 20 boy
charlotte; 21; girl
christy 17 girl') %>>% str_c(collapse = "\n")
library(microbenchmark) # microbenchmark
microbenchmark(test = textData %>>%
str_replace_all("([a-zA-Z0-9]);? ", "\\1,") %>>%
str_c(collapse = "\n") %>>% fread %>>%
setnames(c("name", "age", "sex")) %>>%
mutate(age = as.integer(age)), times = 10L)
# Unit: seconds
# expr min lq mean median uq max neval
# test 4.489137 4.520529 4.528179 4.529275 4.543055 4.557189 10
平均一次4.5秒左右,全距也很小,所以两百万列不是问题
: ==========================================================
: 问题二
: 我的资料中 有些地方没有值 所以当初在存的时候就直接忽略 连空白都没留
: 像这样:
: sam;16;boy; 2015:00:09:59
: green;18;gril
: paul;20; 2015:00:09:59
: 第一行是name
: 第二行是age
: 第三行是性别
: 但是paul没有记录到 所以直接记录到第四行的time
: green的time也没记录到
: 想问有没有什么方法解决 我目前只想到比较笨的方法
: 给它特定范围去判断 像性别不是boy就是gril 出现其他就给他NA
: 还有
: 这样读资料也会因为每列资料col都不一样 有的时候会出现问题
: 是可以读成文字再去慢慢拆开 不过有点笨就是了
: 最后想问如果读资料量上百万笔
: 还是用read.table吗?
: 有没有比较好的函数专门处理large data?
: 谢谢
一样用regex处理即可,速度也是相当快:
pattern <- str_c("([a-z]*);?\\s*", "(\\d*)?;?\\s*", "(boy|girl)?;?\\s*",
"(\\d{4}:\\d{2}:\\d{2}:\\d{2})?")
# 第一个是第一字段,第二个是第二字段,依此类推
readLines(textConnection('sam;16;boy; 2015:00:09:59
green;18;girl;
paul;20; 2015:00:09:59
charlotte; 21;')) %>>% str_replace_all(pattern, "\\1, \\2, \\3, \\4") %>>%
str_replace_all(", , , ", "") %>>% str_c(collapse = "\n") %>>%
fread(na.string="") %>>% setnames(c("name", "age", "sex", "time")) %>>%
mutate(age = as.integer(age))
# name age sex time
# 1 sam 16 boy 2015:00:09:59
# 2 green 18 girl <NA>
# 3 paul 20 <NA> 2015:00:09:59
# 4 charlotte 21 <NA> <NA>
# 这里要为什么要取代", , , ",我暂时想不出来为什么
# 这里不知道为什么经过regex后,每一列会多出三个逗号,让我匪夷所思QQ
# 用两百万个row测试看看:
# data generation
textData <- raply(5e5, 'sam;16;boy; 2015:00:09:59
green;18;girl;
paul;20; 2015:00:09:59
charlotte; 21;') %>>% str_c(collapse = "\n")
library(microbenchmark)
microbenchmark(test = readLines(textConnection(textData)) %>>%
str_replace_all(pattern, "\\1, \\2, \\3, \\4") %>>%
str_replace_all(", , , ", "") %>>% str_c(collapse = "\n") %>>%
fread(na.string="") %>>%
setnames(c("name", "age", "sex", "time")) %>>%
mutate(age = as.integer(age)), times = 10L)
# Unit: seconds
# expr min lq mean median uq max neval
# test 10.93214 10.9493 10.9683 10.96072 10.98294 11.04314 10
平均一次11秒左右,全距也很小,所以两百万列不是问题
最后murmur,这个资料真的长得很丑,我花了一小时才把这篇打完
还在测试不用regular expression的方法,能多快
发现读一次档案还是要80秒,实在太慢,最后就不PO上来了
这里推荐一个网站学regex: http://regexone.com/
题外话:这一篇文章值 185 Ptt币 XDD
作者: f496328mm (为什么会流泪)   2016-05-01 10:58:00
感谢!这应该算是高阶写法吧,又学到新东西啦

Links booklink

Contact Us: admin [ a t ] ucptt.com