我有一个超过40000列的数据文件。在标题中,每列的名称以C1,c2,...,cn开头,并且每组c具有一个或几个子集,例如c1。有2个子集。我需要删除每组c的第一列(子集)。例如,如果输入如下:
输入:
c1.20022 c1.31012 c2.44444 c2.87634 c2.22233 c3.00444 c3.44444
1 1 0 1 0 0 0 1
2 0 1 0 0 1 0 1
3 0 1 0 0 1 1 0
4 1 0 1 0 0 1 0
5 1 0 1 0 0 1 0
6 1 0 1 0 0 1 0
我需要输出如:
c1.31012 c2.87634 c2.22233 c3.44444
1 0 0 0 1
2 1 0 1 1
3 1 0 1 0
4 0 0 0 0
5 0 0 0 0
6 0 0 0 0
7 1 0 0 0
有什么建议吗?
更新:如果行中的数字之间没有空格(这是我的数据集的真实情况)那么我该怎么办?我的意思是我的真实数据看起来像这样: 输入:
c1.20022 c1.31012 c2.44444 c2.87634 c2.22233 c3.00444 c3.44444
1 1010001
2 0100101
3 0100110
4 1010010
5 1010010
6 1010010
并输出:
c1.31012 c2.87634 c2.22233 c3.44444
1 0001
2 1011
3 1010
4 0000
5 0000
6 0000
7 1000
答案 0 :(得分:2)
Perl解决方案:它首先读取标题行,使用正则表达式在点之前提取列名,并保留要保留的列号列表。然后,它使用索引仅打印标题和剩余行中的所需列。
#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };
my @header = split ' ', <>;
my $last = q();
my @keep;
for my $i (0 .. $#header) {
my ($prefix) = $header[$i] =~ /(.*)\./;
if ($prefix eq $last) {
push @keep, $i + 1;
}
$last = $prefix;
}
unshift @header, q();
say join "\t", @header[@keep];
while (<>) {
my @columns = split;
say join "\t", @columns[@keep];
}
更新
#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };
my @header = split ' ', <>;
my $last = q();
my @keep;
for my $i (0 .. $#header) {
my ($prefix) = $header[$i] =~ /(.*)\./;
if ($prefix eq $last) {
push @keep, $i;
}
$last = $prefix;
}
say join "\t", @header[@keep];
while (<>) {
my ($line_number, $all_digits) = split;
my @digits = split //, $all_digits;
say join "\t", $line_number, join q(), @digits[@keep];
}