Сравните столбцы разных файлов с разными размерами и замените несовпадающие значения на NA

Сравните столбцы разных файлов с разными размерами и замените несовпадающие значения на NA

У меня есть три фрейма данных:

Кадр данных 1

chr start end Id chr1 1 400 SN_1 chr1 401 800 SN_2 chr1 801 1200 SN_3 chr1 1201 1600 SN_4 chr1 1601 2000 SN_5 chr1 2001 2400 SN_6 chr1 2401 2800 SN_7

Кадр данных 2

chr start end Id chr1 401 800 SN_2 chr1 801 1200 SN_3 chr1 1201 1600 SN_4

Кадр данных 3

chr start end Id chr1 1201 1600 SN_4 chr1 1601 2000 SN_5 chr1 2001 2400 SN_6

и я хотел бы получить окончательный фрейм данных, где в соответствии с 4-м столбцом 1-го фрейма данных будет сообщено о совпадении или несовпадении по отношению к 4-му столбцу 2-го и 3-го фреймов данных. В новом фрейме данных, если совпадение присутствует, будет сообщен тот же Id, но в случае, если совпадение будет присутствовать, имя Id будет заменено на NA. Может быть, просто запись ввода и вывода будет проще для понимания. Что-то вроде этого:

Желаемый результат:

chr start end Id Id Id chr1 1 400 SN_1 NA NA chr1 401 800 SN_2 SN_2 NA chr1 801 1200 SN_3 SN_3 NA chr1 1201 1600 SN_4 SN_4 SN_4 chr1 1601 2000 SN_5 NA SN_5 chr1 2001 2400 SN_6 NA SN_6 chr1 2401 2800 SN_7 NA NA

Я пробовал с join в команде unix, но не могу сравнить фрейм данных разного размера. Любая идея будет действительно оценена.

решение1

awkрешение:

awk 'FILENAME == ARGV[1] && NR>1{ df2[$2,$3,$4] }
     FILENAME == ARGV[2] && FNR>1{ df3[$2,$3,$4] }
     FILENAME == ARGV[3]{ if(FNR == 1) { printf("%s\t%s\t%s\n",$0,$NF,$NF) } 
     else { printf("%s\t%s\t%s\n",$0, (($2,$3,$4) in df2)? $NF :"NA",(($2,$3,$4) in df3)? $NF :"NA")} 
}' df2 df3 df1 | column -t

Выход:

chr   start  end   Id    Id    Id
chr1  1      400   SN_1  NA    NA
chr1  401    800   SN_2  SN_2  NA
chr1  801    1200  SN_3  SN_3  NA
chr1  1201   1600  SN_4  SN_4  SN_4
chr1  1601   2000  SN_5  NA    SN_5
chr1  2001   2400  SN_6  NA    SN_6
chr1  2401   2800  SN_7  NA    NA

  • df2, df3и df1ваши 2-й, 3-й и 1-йдатафреймфайлы соответственно

  • FILENAME- встроенная переменная, указывающая на имя текущего обрабатываемого файла

  • ARGV- встроенная переменная, указывающая на все аргументы, переданные скрипту awk. ie ARGV[1]содержитdf2

  • FILENAME == ARGV[1] && NR>1- встречаем 1-й файл (т.е. df2), начиная со 2-й строки

    • df2[$2,$3,$4]- захват важнейших ценностей из "Кадр данных 2"как ключ массиваdf2
  • FILENAME == ARGV[2] && FNR>1- встречаем 2-й файл (т.е. df3), начиная со 2-й строки

    • df3[$2,$3,$4]- захват важнейших ценностей из "Кадр данных 3"как ключ массиваdf3
  • FILENAME == ARGV[3]- столкнувшись с 3-м файлом (т.е. df1), главныйКадр данных

решение2

perl -lane '$,="\t";
   !@ARGV and $. == 1 and print($_, qw/Id/x2),next;
   $h{$F[1],$F[2]}->[@ARGV] = $F[3];
   !@ARGV and print $_, map { $h{$F[1],$F[2]}->[$_] // q/NA/ } 1..2;
   $. = 0 if eof;
' file3 file2 file1

Полученные результаты

chr    start   end     Id       Id      Id
 chr1   1       400     SN_1    NA      NA
 chr1   401     800     SN_2    SN_2    NA
 chr1   801     1200    SN_3    SN_3    NA
 chr1   1201    1600    SN_4    SN_4    SN_4
 chr1   1601    2000    SN_5    NA      SN_5
 chr1   2001    2400    SN_6    NA      SN_6
 chr1   2401    2800    SN_7    NA      NA

Выработки

  • Порядок входных данных: dataframe3, dataframe2 и dataframe1.
  • Предположим, что в dataframe1 заполнены все 4-е столбцы, то есть, нет ни одного пропущенного столбца.
  • Вызываем Perlв режиме чтения строки+авторазделения:perl -lane
  • Во время чтения 3-го кадра @ARGV содержит 2 элемента, во время чтения 2-го кадра — 1 элемент, а во время чтения 3-го кадра — 0 элементов.
  • Мы заполняем хеш, %hключами которого являются 2-е и 3-е поля, $F[1],$F[2]а значениями — анонимные ссылки на массив, поэтому он называется: $h{...}[...].
  • В течение времени 1-го кадра данных (@ARGV, имеющий 0 элементов) мы печатаем каждую строку с содержимым 1-го кадра данных и определяем, существуют ли элементы массива для 2-го/3-го кадров для соответствующих текущих 2-го/3-го полей.

Связанный контент