我有一个制表符分隔的文件,如下所示:
"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)
,但没有帮助。
答案 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
希望有帮助。