3

I have a genotype.file with 317 columns (1, 2, 3, ..., 317). In the example below I am just showing the first few columns!

Input genotype.file:

Chr00c0002  56240   N   N   N   A   N   A   N   N   N   N   N   A   
Chr00c0040  55087   N   N   N   C   N   N   N   N   N   N   N   N   
Chr00c0041  24730   N   N   N   A   N   A   N   N   N   N   N   N   
...

I want to keep only those columns that match to each of my count.files. This is one of my count files and I have in total 50 count file (count.file.1, count.file.2, ..., count.file.50)!

cat count.file.1
51
92
166
169
196
199
213
228
229
284
291
297

So for the first count.file I want to keep only columns 51, 92, 166, 169, ... from the genotype.file.

1
  • Oh no, I just showed the first few columns of genotype file here, the real one has 317 columns. I edited slightly!
    – Anna1364
    Commented Oct 6, 2017 at 20:03

2 Answers 2

2

Assuming that the genotype.file file is tab-delimited:

cut -f $(tr '\n' ',' <count.file.1 | sed 's/,$//') genotype.file

The command substitution, $( tr ... | sed ... ), generates a comma-delimited list of column numbers for cut to cut from the input file.

The tr replaces all newlines by commas in the count.file.1 file, while sed removes the extra comma at the end.

The resulting command will look like the following, given the example data:

cut -f 51,92,166,169,196,199,213,228,229,284,291,297 genotype.file

To loop over your count.file.* files:

for cfile in count.file.*; do
    cut -f $(tr '\n' ',' <"$cfile" | sed 's/,$//') genotype.file >genotype-"${cfile##*.}"
done

This creates new file called genotype-N where N is the number corresponding to the count.file.N that was used to generate it from genotype.file. The number is extracted from the end of the filename.


If genotype.file is not tab-delimited, you may make it tab-delimited:

tr -s ' ' '\t' <genotype.file >genotype.tsv

This assumes that the columns in the original file are separated by only spaces. The tr command will replace multiple consecutive spaces with a tab. The result is redirected to a new file. You would use the cut command above on this new file.


Using awk

awk 'NR == FNR { c[++n] = $0; next } { t=$c[1]; for (i=2; i<=n; ++i) t = t OFS $c[i]; print t }' count.file.1 genotype.file

This will first read count.file.1 to get the columns that we'd like to extract from genotype.file into the array c, and then, when we read genotype.file, those column numbers are used to extract the data. t is a temporary variable that holds the output line constructed from the selected columns.

To loop over your count.file.* files:

for cfile in count.file.*; do
    awk 'NR == FNR { c[++n] = $0; next } { t=$c[1]; for (i=2; i<=n; ++i) t = t OFS $c[i]; print t }' \
        "$cfile" genotype.file >genotype-"${cfile##*.}"
done

This creates new file called genotype-N in the same manner as with the cut solution.

1

Using awk only with simple script.

awk '{ printf "{ print ";for(i=1; i<NF; i++){ printf "$%d, ",$i};
       print "$"$i" }" }' <<< "$(awk '{printf $0" "}' count.file.{1..50})" >genotype.awk

This will produces an awk script called genotype.awk like below, which will collect all column-numbers are in all count.file.{1..50} files. We used Brace Expansion here to read all those 50 files by awk.

{ print $51, $92, $166, $169, $196, $199, $213, $228, $229, $284, $291, $297, ... }

Usage:

awk -f genotype.awk genotype.file

This will perform executing genotype.awk script on genotype.file file and will print included columns-number only.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .