转换R或perl中的表

时间:2016-02-25 16:07:36

标签: r bash perl

是否可以将此表读入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

3 个答案:

答案 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