Как удалить всю строку, если более 60% или более столбцов после определенного столбца содержат одно и то же конкретное значение? - PullRequest
3 голосов
/ 12 апреля 2019

У меня есть очень большой разделенный табуляцией файл, как показано ниже (примерно 300 столбцов и 1,2 миллиона строк). Все столбцы форматируются одинаково после столбца 4 (только с разными номерами, но все они форматируются с #/# или ./.)

The headings seem to be to long resulting in a bit of shifted look

CHROM   POS     REF     ALT     LarsenP1_1_PI173627.sort        LarsenP1_1_PI173630.sort        LarsenP1_1_PI204384.sort        LarsenP1_1_PI204386.sort        LarsenP1_1_PI204550.sort
1J_LG1  393466  A       [C]     ./.     1/2     1/1     0/0     0/1     
1J_LG1  393472  G       [A, C]  5/6     ./.     ./.     1/0     0/0         
1J_LG1  393475  G       [A]     ./.     ./.     ./.     ./.     ./.     
1J_LG1  393482  T       [C]     0/0     1/1     1/2     2/2     ./.
1J_LG1  393762  A       [C]     0/0     ./.     ./.     2/2     ./.   

Я пытаюсь удалить все строки со значениями ./. в 60% или более каждого столбца после столбца 4 (не включая столбец 4, поэтому столбец 5 и далее). По существу, в приведенном выше примере строки 3 и 5 будут удалены. Это должно привести к выводу, как показано ниже.

CHROM   POS     REF     ALT     LarsenP1_1_PI173627.sort        LarsenP1_1_PI173630.sort        LarsenP1_1_PI204384.sort        LarsenP1_1_PI204386.sort        LarsenP1_1_PI204550.sort
1J_LG1  393466  A       [C]     ./.     1/2     1/1     0/0     0/1
1J_LG1  393472  G       [A, C]  5/6     ./.     ./.     1/0     0/0
1J_LG1  393482  T       [C]     0/0     ./.     ./.     2/2     ./.

Я очень новичок в программировании и биоинформатике и буду очень признателен за помощь. Проведя некоторые исследования, я думаю, что я должен использовать что-то вроде awk или sed, но я не уверен.

Также извините, если форматирование не очень хорошее.

Ответы [ 2 ]

1 голос
/ 13 апреля 2019

Поскольку ./. и 0/0 появляются в полях только после # 4 и всегда являются полями, все, что вам нужно:

$ awk -F'\t' 'gsub(/\.\/\./,"&") < ((NF-4)*.6)' file
CHROM   POS     REF     ALT     LarsenP1_1_PI173627.sort        LarsenP1_1_PI173630.sort        LarsenP1_1_PI204384.sort        LarsenP1_1_PI204386.sort     LarsenP1_1_PI204550.sort
1J_LG1  393466  A       [C]     ./.     1/2     1/1     0/0     0/1
1J_LG1  393472  G       [A, C]  5/6     ./.     ./.     1/0     0/0
1J_LG1  393482  T       [C]     0/0     1/1     1/2     2/2     ./.

$ awk -F'\t' 'gsub(/\.\/\.|0\/0/,"&") < ((NF-4)*.6)' file
CHROM   POS     REF     ALT     LarsenP1_1_PI173627.sort        LarsenP1_1_PI173630.sort        LarsenP1_1_PI204384.sort        LarsenP1_1_PI204386.sort     LarsenP1_1_PI204550.sort
1J_LG1  393466  A       [C]     ./.     1/2     1/1     0/0     0/1
1J_LG1  393482  T       [C]     0/0     1/1     1/2     2/2     ./.
1 голос
/ 12 апреля 2019

1-е решение: Не могли бы вы попробовать следующее.

awk '{for(i=5;i<=NF;i++){val=$i;sum+=sub(/\.\/\./,"",val)};if((sum/(NF-4))*100<60){print};sum=""}'   Input_file

ИЛИ (добавление формы не одного вкладыша вышеуказанного решения)

awk '
{
  for(i=5;i<=NF;i++){
    val=$i
    sum+=sub(/\.\/\./,"",val)
  }
  if((sum/(NF-4))*100<60){
    print
  }
  sum=""
}'  Input_file

2-е решение: Или это может быть быстрее (хотя и не проверено на миллионах строк).

awk '{for(i=5;i<=NF;i++){if($i ~ /^\.\/\.$/){sum++}};if((sum/(NF-4))*100<60){print};sum=""}'  Input_file

ИЛИ (aне одна строка в указанном выше решении):

awk '
{
  for(i=5;i<=NF;i++){
    if($i ~ /^\.\/\.$/){
      sum++
    }
  }
  if((sum/(NF-4))*100<60){
      print
  }
  sum=""
}'   Input_file

Если у вас есть данные с разделителями TAB, измените awk на awk 'BEGIN{FS=OFS="\t"}.... и в вышеприведенных кодах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...