是否可以将此表读入R
739132 tolerated(0.56) benign(0.302)
819973 unknown(0)
861275 benign(0.106)
861277
861329 deleterious(0) possibly_damaging(0.816)
问题在于 1)不是每一行都有相同数量的列 - 有空列和columsn哪一方应填写NA这样
739132 tolerated 0.56 benign 0.302
819973 NA NA unknown 0
861275 NA NA benign 0.106
861277 NA NA NA NA
861329 deleterious 0 possibly_damaging 0.816
- 有5列 - 可能在R?否则是否有一个bash命令或perl方式来转换commadn行上的表?
也可能只有第一列有一个值 - 比如有害(0)然后是空的 - 然后读入应该只是位置有害0 NA NA
答案 0 :(得分:0)
这比我想要的有点丑,但它确实有效。对于它的价值,这个解决方案对间距,标签数量等不敏感 - 它只是拉动使用正则表达式来拉出所需的部分。
获取原始数据:
dd <- readLines(textConnection("739132 tolerated(0.56) benign(0.302)
819973 unknown(0)
861275 benign(0.106)
861277
861329 deleterious(0) possibly_damaging(0.816)"))
可以在基础R中完成,但stringr
有一些方便的工具。
library(stringr)
words <- sapply(str_extract_all(dd,"[[:alpha:]]+\\("),
str_replace,"\\(","")
nums <- str_extract_all(dd,"[0-9.]+")
现在适当填充NA值
pad <- function(x) c(rep(NA,2-length(x)),x)
nums <- t(sapply(nums,
function(x) as.numeric(c(x[1],pad(x[-1])))))
words <- t(sapply(words,pad))
将各个部分放在一起
setNames(data.frame(nums[,1],words[,1],nums[,2],words[,2],nums[,3]),
paste0("V",1:5))
答案 1 :(得分:0)
此perl解决方案使用任意数量的字段处理制表符分隔文件。在程序开始时,它获取任意行中的最大选项卡数,并将其乘以2以获得预期列。
更新:更改了代码以处理尾随空记录。
#!/usr/bin/perl
use strict;
use warnings;
use List::Util 'max';
open my $fh, '<', 'test.csv' or die $!;
chomp(my @data = <$fh>);
close $fh or die $!;
my $cols = 2 * max map tr/\t//, @data;
for (@data) {
my ($key, @rest) = split /\t/;
@rest = map {length() ? /(\w+)\((.+)\)/ : ('NA') x 2} @rest;
push @rest, 'NA' while @rest < $cols;
print join("\t", $key, @rest), "\n";
}
__DATA__
*** contents of test.csv (tab separated)
111111
739132 tolerated(0.56) benign(0.302)
819973 unknown(0)
861275 benign(0.106)
861277
861329 deleterious(0) possibly_damaging(0.816)
871111 firstfield(9)
输出
111111 NA NA NA NA
739132 tolerated 0.56 benign 0.302
819973 NA NA unknown 0
861275 NA NA benign 0.106
861277 NA NA NA NA
861329 deleterious 0 possibly_damaging 0.816
871111 firstfield 9 NA NA
答案 2 :(得分:0)
这就是我想出来的。 假设第4行有空字段的选项卡,而不是没有字段。 (我不确定,因为复制粘贴)
#!/usr/bin/env perl
use strict;
use warnings;
while ( <DATA> ) {
my @row = split /\t/;
for( @row ) {
#digit only
/^\d+$/ && print;
#word with bracketed value
/(\w+)\((.+)\)/ && print "$1\t$2";
#empty field
/^$/ && print "NA\tNA";
#new delim
print "\t";
}
print "\n";
}
__DATA__
739132 tolerated(0.56) benign(0.302)
819973 unknown(0)
861275 benign(0.106)
861277
861329 deleterious(0) possibly_damaging(0.816)
打印:
739132 tolerated 0.56 benign 0.302
819973 NA NA unknown 0
861275 NA NA benign 0.106
861277 NA NA NA NA
861329 deleterious 0 possibly_damaging 0.816