如何在R中读取具有许多空白字段的数据

时间:2019-09-18 22:04:11

标签: r data.table

我有一个制表符分隔的文件,如下所示:

"ID\tV1\tV2\tV3\tV4\tV5\n\t1\tA\t\t\t\t1\n\t2\tB\t\t\t\t2"

我使用以下代码读取数据:

df <- read.table("path/to/file",header=TRUE,fill=TRUE)

结果是这样的:

df
  id V1 V2 V3 V4 V5
1  1  A  1 NA NA NA
2  2  B  2 NA NA NA

但是我希望这样:

df
  id V1 V2 V3 V4 V5
1  1  A  NA NA NA 1
2  2  B  NA NA NA 2

我已经尝试过sep="\t"na.strings=c(""," ",NULL),但没有帮助。

3 个答案:

答案 0 :(得分:1)

我无法使其与read.table一起使用,那么如何手动解析字符串

ss <- "ID\tV1\tV2\tV3\tV4\tV5\n\t1\tA\t\t\t\t1\n\t2\tB\t\t\t\t2"

library(tidyverse)

entries <- unlist(str_split(ss, "\t"))
ncol <- str_which(entries, "\n")[1]
entries %>%
    str_remove("\\n") %>%
    matrix(ncol = ncol, byrow = T, dimnames = list(NULL, .[1:ncol])) %>%
    as.data.frame() %>%
    slice(-1) %>%
    mutate_if(is.factor, as.character) %>%
    mutate_all(parse_guess)
#  ID V1 V2 V3 V4 V5
#1  1  A NA NA NA  1
#2  2  B NA NA NA  2

说明:我们在"\t"上分割了字符串; "\n"的第一次出现告诉我们我们有多少列。然后,我们通过删除换行符"\n"来整理条目,将其重塑为matrix,然后重塑为data.frame,修复标题,并让readr::parse_guess猜测每列。

为了很好的衡量,我们可以将所有内容汇总为一个函数

read.my.data <- function(s) {
    entries <- unlist(str_split(s, "\t"))
    ncol <- str_which(entries, "\n")[1]
    entries %>%
        str_remove("\\n") %>%
        matrix(ncol = ncol, byrow = T, dimnames = list(NULL, .[1:ncol])) %>%
        as.data.frame() %>%
        slice(-1) %>%
        mutate_if(is.factor, as.character) %>%
        mutate_all(parse_guess)
}

并确认

read.my.data(ss)
#  ID V1 V2 V3 V4 V5
#1  1  A NA NA NA  1
#2  2  B NA NA NA  2

答案 1 :(得分:1)

data.table的fread()读入字符串没有问题...但是您的数据似乎有\t太多(在每个\ n之后),这导致创建了额外的列。

最好在创建文件的导出中修复此问题。

如果这不可能,则可以调整fread()的参数以获得所需的输出。

在这里我们使用drop来删除由于多余的\t而创建的第一列。
为了找回正确的列名,我们再次读取文件的第一行

string <- "ID\tV1\tV2\tV3\tV4\tV5\n\t1\tA\t\t\t\t1\n\t2\tB\t\t\t\t2"
data.table::fread( string, 
                   drop = 1, 
                   fill = TRUE, 
                   col.names = as.matrix( fread(string, nrows = 1, header = FALSE))[1,] )


   ID V1 V2 V3 V4 V5
1:  1  A NA NA NA  1
2:  2  B NA NA NA  2

答案 2 :(得分:1)

正如Quar在他/她的评论中已经提到的那样,您的文件在每一行的开头都有一个额外的标签,因此列标签的数量与数据字段的数量不匹配:

> foo <- "ID\tV1\tV2\tV3\tV4\tV5\n\t1\tA\t\t\t\t1\n\t2\tB\t\t\t\t2"
> cat(foo, "\n")
ID      V1      V2      V3      V4      V5
        1       A                               1
        2       B                               2 

如果附加的第一列包含唯一的行名,则可以。 因此,有两种方法可以解决该问题:1.删除空列(理想情况下,通过解决生成该文件的过程来解决)或2.解决行名问题。

这是我使用第二种选择的建议:

由于数据是用制表符分隔的,因此我将使用read.delim,它只是read table,此类文件具有合理的默认值。当然,在不进行任何调整的情况下会引发错误(“不允许重复的“ row.names””)。为了解决这个问题,我们需要告诉它使用自动行编号。这样一来,您几乎可以得到所需的一切:

> read.delim(text=foo, row.names=NULL)
  row.names ID V1 V2 V3 V4 V5
1            1  A NA NA NA  1
2            2  B NA NA NA  2

剩下要做的就是摆脱row.names列。另外,您可能希望将ID列变成row.names:

> read.delim(text=foo, row.names='ID')
  row.names V1 V2 V3 V4 V5
1            A NA NA NA  1
2            B NA NA NA  2

希望有帮助。