【发布时间】:2019-09-09 01:22:11
【问题描述】:
我有一个非常大的数据集,其中包含许多列,是从应用程序导出的。问题是文件是“空字符”分隔的。使用 readLines 读入文件会产生一个字符串列表,每个字符串具有相同数量的字符。
确定列位置的一种可能方法是检查每个字符串(比如位置 5)是否有一个空字符。因此,可以从向量 1 开始继续搜索,直到找到一个非空字符。
d <- data.frame("V1" = c(" f ggh", "aa hh", "a qq" ), stringsAsFactors =
F)
first.char <- function(col){
current <- 0
j <- 1
while(j <= length(d)){
tmp <- substr(d[j], col, col)
if(!grepl("^\\s*$", tmp)){
current <- 1
break}
j <- j+1
}
return(current)
}
row_dummies <- lapply( c(1:6), first.char) %>% unlist
这种方法有效,但在扩展时非常慢(有 100 万个字符串的列表,每个 1500 个字符长)。我还尝试将每个向量转换为 data.table,然后使用 str split (Split text string in a data.table columns),但这似乎更加低效,因为在大多数情况下不需要检查所有行。
有什么建议或意见吗?
更新: 上面的例子太琐碎了。这个好一点:
text <- c("df ggh a a h h a qq",
" aa hh ab qt",
" fggh aa hh a ")
想要的输出是
list( c("df ggh", "a a", "h h", "a", "qq"),
c(NA, "aa", "hh", "ab", "qq"),
c(" fggh", "aa", "hh", "a", NA)
)
str_locate_all 效果很好,因为它指示在哪里拆分字符串:
cuts_in <- sapply(text, function(x) x %>% str_locate_all(. , "\\s") )
cuts_in <- lapply(cuts_in, data.table) # to data.table
cuts_in <- rbindlist(cuts_in)
cuts_in <- cuts_in[, .N, by=start]
cuts_in[ N==3 ,"start"]
start
1: 7
2: 11
3: 15
4: 18
但是,这可能不是最有效的方式(有 15 个文件,每个文件一百万行,每行有 1500 个字符)。例如,如果第 1 行位置 1 不是空格,则无需检查第 2 行和第 3 行中位置 1 处的字符。 read_table2 似乎也不是解决方案:
read_table2(text, col_names = FALSE)
X1 X2 X3 X4 X5 X6 X7 X8
<chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
1 df ggh a a h h a qq
2 aa hh ab qt NA NA NA NA
3 fggh aa hh a NA NA NA NA
【问题讨论】:
-
以
read.table(text = d$V1, as.is = TRUE)为例。 -
是的,我的例子太简单了。一个可能的区别可能是我不能在每个空字符处拆分。使用 read.table 我得到以下信息: 扫描错误(file = file,what = what,sep = sep,quote = quote,dec = dec,:第 2 行没有 79 个元素
-
我想我对所需的输出有点困惑;每行具有相同数量的字符并不意味着由于空格数量不同,您将拥有相同数量的列。你想要什么而不是
read_table2给你的? -
我不知道事前的列数。我需要找出来,并找出他们在哪里。由于数据的导出方式,如果一个单元格(在数据库中)是一个 NA,它会在我的 txt 文件中打印为“”。这意味着我可以通过逐列查看“”来了解列。在上面的示例中,列拆分候选因此位于位置 7、11、15、18。