Сложный экстракт всех записей строк на основе строкового шаблона с использованием awk, sed или R - PullRequest
0 голосов
/ 10 июля 2019

У меня есть 7-колоночный файл, подобный этому:

ID ANNOTATION OR PVAL VAR_INFO INFO_TAGS_USED_TO_ANNOTATE INFO_TAGS_USED_TO_ANNOTATE
1 ANN1 1.66 0.0028 1:154837796(1.12e-06,0) 1:154834092(1.49e-05,0)|1:154834911(1.2e-05,1)| 1:155008318(0.000201,0)|1:155008973(0.000177,0)|
1 ANN1 1.66 0.0028 3:53707953(1.21e-06,0) 3:53708850(1.68e-06,1)|3:53711735(8.52e-07,1)| |3:53765419(0.0021,0)|
1 ANN1 1.66 0.0028 12:109966662(6.723e-06,0) 12:109888779(3.01e-05,0)|12:109889704(5.242e-05,0)|12:109890955(4.79e-05,0)| 12:110105520(NA,0)|12:110132792(0.00015,0)|12:110155571(3.93e-05,0)|

Я пытаюсь найти решение, используя grep, sed, awk или R. Из текстового файла, разделенного пробелами, мне нужно извлечь все вэкземпляры в столбце 6 (INFO_TAGS_USED_TO_ANNOTATE column), где значение 1 следует после запятой.

Всякий раз, когда встречается 1, информация, которую мне нужно сохранить для каждого экземпляра, с использованием строки 1 в качестве примера, 1:154834911(1.2e-05,1).Эта информация соответствует информации SNP, т. Е. chromosome number:base position(p-value,annotation=1).

Если в конкретной строке встречается более одного экземпляра 1, то мне нужен каждый экземпляр и сообщается соответствующая информация SNP.Таким образом, используя в качестве примера строку 2, будет сообщено о двух экземплярах 3:53708850(1.68e-06,1)|3:53711735(8.52e-07,1).

Если возможно, эта извлеченная информация для каждой строки будет добавлена ​​в новый столбец.

Каждая запись в столбце6 отделяется |.Было бы полезно использовать | в качестве разделителя в новом столбце, если сообщается о нескольких записях для конкретной строки.

Вывод для последнего столбца для вышеприведенного вывода будет выглядеть следующим образом

NewCol
1 1:154834911(1.2e-05,1)
2 3:53708850(1.68e-06,1)|3:53711735(8.52e-07,1)
3 <empty>

Обратите внимание, что информация в столбцах 5, 6 и 7 очень похожа, что может привести к путанице.

Буду признателен за любые предложения.

Ответы [ 4 ]

1 голос
/ 10 июля 2019

Это может сработать для вас (GNU sed): r

sed -E 'h;s/\S+/\n&\n/6;s/.*\n(.*)\n.*/\1/;s/[^,]+,([^1)]|[^)]{2,})\|//g;s/\|$//;1s/.*/newcol/;H;g;s/\n/ /' file

Сделайте копию строки, изолируйте 6-е поле, удалите строки, не содержащие 1 после запятой, удалите окончательный | и добавьте результат к исходной строке.

1 голос
/ 10 июля 2019

Используя R, прочитайте myfile, как в закомментированной строке, а затем используйте gsub для удаления ненужных частей, поместив то, что осталось, в новый столбец. Используемые данные показаны в конце.

library(gsubfn)
# DF <- read.table("myfile", header = TRUE, as.is = TRUE, 
#   check.names = FALSE, strip.white = TRUE)
DF <- read.table(text = Lines, header = TRUE, as.is = TRUE, 
  check.names = FALSE, strip.white = TRUE)

transform(DF, NEWCOL = gsub("([^,]+),[^1]\\)\\|", "", INFO_TAGS_USED_TO_ANNOTATE))

Примечание

Lines <- "
ID ANNOTATION OR PVAL VAR_INFO INFO_TAGS_USED_TO_ANNOTATE INFO_TAGS_USED_TO_ANNOTATE
1 ANN1 1.66 0.0028 1:154837796(1.12e-06,0) 1:154834092(1.49e-05,0)|1:154834911(1.2e-05,1)| 1:155008318(0.000201,0)|1:155008973(0.000177,0)|
1 ANN1 1.66 0.0028 3:53707953(1.21e-06,0) 3:53708850(1.68e-06,1)|3:53711735(8.52e-07,1)| |3:53765419(0.0021,0)|
1 ANN1 1.66 0.0028 12:109966662(6.723e-06,0) 12:109888779(3.01e-05,0)|12:109889704(5.242e-05,0)|12:109890955(4.79e-05,0)| 12:110105520(NA,0)|12:110132792(0.00015,0)|12:110155571(3.93e-05,0)|
"
1 голос
/ 10 июля 2019

Использование любого awk в любой оболочке на каждом компьютере UNIX:

$ cat tst.awk
NR==1 { print $0, "NewCol"; next }
{
    new = sep = ""
    n = split($6,f,/[|]/)
    for (i=1; i<=n; i++) {
        if ( f[i] ~ /,1/ ) {
            new = new sep f[i]
            sep = "|"
        }
    }
    print $0, new
}

$ awk -f tst.awk file
ID ANNOTATION OR PVAL VAR_INFO INFO_TAGS_USED_TO_ANNOTATE INFO_TAGS_USED_TO_ANNOTATE NewCol
1 ANN1 1.66 0.0028 1:154837796(1.12e-06,0) 1:154834092(1.49e-05,0)|1:154834911(1.2e-05,1)| 1:155008318(0.000201,0)|1:155008973(0.000177,0)| 1:154834911(1.2e-05,1)
1 ANN1 1.66 0.0028 3:53707953(1.21e-06,0) 3:53708850(1.68e-06,1)|3:53711735(8.52e-07,1)| |3:53765419(0.0021,0)| 3:53708850(1.68e-06,1)|3:53711735(8.52e-07,1)
1 ANN1 1.66 0.0028 12:109966662(6.723e-06,0) 12:109888779(3.01e-05,0)|12:109889704(5.242e-05,0)|12:109890955(4.79e-05,0)| 12:110105520(NA,0)|12:110132792(0.00015,0)|12:110155571(3.93e-05,0)|
1 голос
/ 10 июля 2019

Perl будет хорошо работать здесь:

perl -lane '
    if ($. == 1) {
        $val = "NewCol";
    } else {
        $val = join "|", grep {/,1\)/} split /\|/, $F[5];
    }
    print join " ", @F, $val;
' file
ID ANNOTATION OR PVAL VAR_INFO INFO_TAGS_USED_TO_ANNOTATE INFO_TAGS_USED_TO_ANNOTATE NewCol
1 ANN1 1.66 0.0028 1:154837796(1.12e-06,0) 1:154834092(1.49e-05,0)|1:154834911(1.2e-05,1)| 1:155008318(0.000201,0)|1:155008973(0.000177,0)| 1:154834911(1.2e-05,1)
1 ANN1 1.66 0.0028 3:53707953(1.21e-06,0) 3:53708850(1.68e-06,1)|3:53711735(8.52e-07,1)| |3:53765419(0.0021,0)| 3:53708850(1.68e-06,1)|3:53711735(8.52e-07,1)
1 ANN1 1.66 0.0028 12:109966662(6.723e-06,0) 12:109888779(3.01e-05,0)|12:109889704(5.242e-05,0)|12:109890955(4.79e-05,0)| 12:110105520(NA,0)|12:110132792(0.00015,0)|12:110155571(3.93e-05,0)|

Это магия: $val = join "|", grep {/,1\)/} split /\|/, $F[5]; - вы должны читать справа налево:

  • сначала разделить 6-е поле (perl использует индексирование на основе 0) с помощью канала (который является специальным символом регулярного выражения, поэтому необходима осторожность,
  • затем оставьте только биты с "1" после запятой и перед закрывающей скобкой,
  • затем соедините оставшиеся биты с конвейером.

Если вы хотите раздражать своих коллег, это может быть сведено до

perl -lape '$_=join" ",@F,$.==1?"NewCol":join"|",grep{/,1\)/}split/[|]/,$F[5]' file
...