5

I have 2 files as input:

File 1 (space separated)

ID POS a0 a1
SNP1 123 A C
SNP2 456 T C
SNP3 789 G A

File 2 (space separated)

0 1 0 1 0 0 0 1
1 1 0 0 1 0 0 1
0 1 1 1 0 0 0 1

Required output

A C A C A A A C
C C T T C T T C
G A A A G G G A 

Each line in file 2 represent 1 Line in File 1, the trick is to substitute the 0 and 1 for the corresponding letter in a0 and a1 respectively. This is just a small example, the real file is huge, more than 600K lines.

I am looking for an awk or perl solution.

3
  • The first line of your required output looks incorrect based on the algorithm you've mandated... Shouldn't it be A C A C A A A C ? – John Nov 25 '15 at 17:31
  • Sorry, my bad, thanks for pointing out the mistake, now is correct. – Bernabé Bustos Becerra Nov 25 '15 at 17:33
  • Looks like DNA stuff, doesn't it? Sorry, just for curiosity… – Andreas Wiese Nov 25 '15 at 22:02
3

As an illegible awk one-liner

$ awk 'NR>1{a[0]=$3;a[1]=$4;getline<f;for(i=1;i<=NF;i++)$i=a[$i];print}' f=file2 file1
A C A C A A A C
C C T T C T T C
G A A A G G G A

More readable:

awk '
    # skip the header in file1
    NR == 1 {next}
    {
        # read the values from the file1 line
        a[0] = $3
        a[1] = $4

        # replace the current record with the corresponding line from the map file
        getline < map_file

        # and now substitute the 0/1 with the values
        for (i=1; i<=NF; i++)
            $i = a[$i]
        print
    }
' map_file=file2  file1
2

You can do this fully in awk but as a variation here's an awk + paste solution. You'll need bash or another shell that supports process substitution

paste <(tail -n +2 file1) file2 | 
awk '{a["0"]=$3; a["1"]=$4; for (i=5; i<=NF; ++i) printf "%s%s", a[$i], i==NF?"\n": " "}'

The tail -n +2 is needed to skip the header line from file1.

0
#!/usr/bin/env perl
# TODO docs on usage here, or write perldocs below, etc.
use strict;
use warnings;

die "Usage: $0 headerfile datafile\n" if @ARGV != 2;

my ($headerfile, $datafile) = @ARGV;

open(my $hfh, '<', $headerfile) or die "could not open '$headerfile': $!\n";
open(my $dfh, '<', $datafile) or die "could not open '$datafile': $!\n";

readline $hfh; # skip the header line

my $lineno = 1;
while (!eof($hfh) and !eof($dfh)) {
  my $convert_to = join '', (split ' ', scalar readline $hfh)[-2,-1];
  die sprintf "no conversion at $headerfile:%d\n", $lineno+1
    if !defined $convert_to;

  $_ = readline $dfh;
  die "no data to convert at $datafile:$lineno\n" if !defined;

  eval "tr/01/$convert_to/, 1" or die $@;
  print;

  $lineno++;
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.