Объединить некоторые файлы с разделителями табуляции

У меня есть 100 файлов с 57 816 строк каждый. Я хочу сделать внешнее объединение этих файлов, объединившись на основе общего столбца.

Для этого я использую R-программирование, но это очень медленно.

fileList <- list.files(, pattern=".txt") pm_list=lapply(fileList, read.table) merged_pm=merge_all(pm_list, by = "gene_short_name") 

Есть ли быстрый способ сделать это в bash? Другим методом, который я могу использовать, является SQL, но сначала мне нужно создать 100 таблиц, а затем загрузить их до объединения, что не очень эффективно.

Количество строк одинаково в каждом файле, поэтому я хочу объединиться на основе общего столбца и не могу использовать cbind из R, поскольку константы в общем столбце немного вверх и вниз в разных файлах и не присутствуют в одном месте в каждом файле. Ниже приведены два файла-образца. Я хочу присоединиться на основе 'gene_short_name'

 gene_short_name FPKM56 MT-TF 0.90 MT-TV 0 MT-RNR1 310.015 MT-TL1 0 MT-TM 0 

Файл 2 приведен ниже:

 gene_short_name FPKM53 MT-TF 0 MT-TV 0.344 MT-TM 0.10 MT-TL1 0 MT-RNR1 0 MT-ND2 158.332 

2 Solutions collect form web for “Объединить некоторые файлы с разделителями табуляции”

Следующий скрипт должен выполнить внешнее соединение в столбце (поле) 1 всех файлов с разделителями табуляции, переданных в качестве аргументов. Он использует команду join , которая выполняет внешнее объединение в отсортированных файлах, по 2 файла за раз.

Он будет присоединяться к каждой строке в файлах, включая строки заголовков. Если вы хотите, чтобы заголовки были исключены, измените две команды sort на то, что создает отсортированный файл, который их не учитывает.

 #!/bin/sh if test $# -lt 2 then echo usage: gjoin file1 file2 ... exit 1 fi sort -t $'\t' -k 1 "$1" > result shift for f in "$@" do sort -t $'\t' -k 1 "$f" > temp join -1 1 -2 1 -t $'\t' result temp > newresult mv newresult result done cat result rm result temp 

Если у вас установлена ​​более старая оболочка, $'\t' не будет заменена вкладкой, поэтому вам нужно будет использовать « TAB » , где вы помещаете литеральную вкладку между кавычками.

Оптимизации возможны, если вместо /bin/sh вы можете использовать современную оболочку, такую ​​как bash или ksh; например, линии

 sort -t $'\t' -k 1 "$f" > temp join -1 1 -2 1 -t $'\t' result temp > newresult 

можно заменить на

 join -1 1 -2 1 -t $'\t' result <(sort -t $'\t' -k 1 "$f") > newresult 

Поскольку в вашем столбце ключи в первом столбце всегда одинаковы (только порядок отличается) Я думаю, что вы могли бы сделать это быстрее с sort , cut и paste . Вы можете отсортировать один из файлов (исключая первые две строки), а затем отсортировать остальные файлы (опять же, исключая первые две строки) и извлечь только второй столбец из каждого из них и вставить результаты. Пример:
1.txt :

 g_s_n FPKM56 MT-ND2 21.06 MT-TF 0.90 MT-TV 1 MT-RNR1 310.015 MT-TL1 1 MT-TM 1 

2.txt :

 g_s_n FPKM53 MT-TF 0 MT-TV 0.344 MT-TM 0.10 MT-TL1 0 MT-RNR1 0 MT-ND2 158.332 

3.txt :

 g_s_n FPKM58 MT-RNR1 0.82 MT-TM 7 MT-TF 1.20 MT-TV 4 MT-ND2 4.05 MT-TL1 2 

Бег:

 paste <({ head -n 2; sort; } <1.txt) <({ head -n 2; sort; } <2.txt | cut -f2) \ <({ head -n 2; sort; } <3.txt | cut -f2) 

производит:

 g_s_n FPKM56 FPKM53 FPKM58 MT-ND2 21.06 158.332 4.05 MT-RNR1 310.015 0 0.82 MT-TF 0.90 0 1.20 MT-TL1 1 0 2 MT-TM 1 0.10 7 MT-TV 1 0.344 4 

Как это работает: { head -n 2; sort; } <1.txt { head -n 2; sort; } <1.txt { head -n 2; sort; } <1.txt сортирует первый файл (кроме первых двух строк), поэтому первый столбец (общий) теперь сортируется:

 g_s_n FPKM56 MT-ND2 21.06 MT-RNR1 310.015 MT-TF 0.90 MT-TL1 1 MT-TM 1 MT-TV 1 

То же самое для других файлов: { head -n 2; sort; } <other_files.txt | cut -f2 { head -n 2; sort; } <other_files.txt | cut -f2 { head -n 2; sort; } <other_files.txt | cut -f2 , только на этот раз мы извлекаем второй столбец (после sort первый столбец идентичен для всех файлов):

 FPKM53 158.332 0 0 0 0.10 0.344 

а также:

 FPKM58 4.05 0.82 1.20 2 7 4 

все они объединены paste .


Несомненно, вышеизложенное отлично подходит для ограниченного количества файлов, и если ваша оболочка поддерживает замещение процесса. В противном случае вам придется писать сценарий и использовать временные файлы (как Марк делает в своем ответе), вставлять файлы в партиях по 10, 20 и т. Д. В зависимости от системных ограничений.

  • Как создать загрузочную флешку для «efi-shell»
  • Как вы просматриваете подкаталог, где путь содержит пробелы?
  • Как знак двоеточия и знак вопроса доллара объединяются в sh?
  • Как получить путь, индекс строки и содержимое строки в оболочке bash?
  • Escape filepath
  • Относительно отдельного файла в несколько файлов в соответствии с разделом строк
  • Выполнение всех сценариев оболочки в каталоге, начинающемся с буквы 'a'
  • Возможно ли напечатать повторяющийся диапазон аргументов через cli из csv? (см. пример)
  • xargs не запрашивает после каждой строки
  • Сделать Trickle получить правильную $ PATH
  • Выход Capture (sdout / stderr) отправителя SSH-порта
  • Interesting Posts

    сделать терминал реальным прозрачным

    midnight commander: правила доступа к архивам через VFS

    Почему номера системных вызовов Linux в x86 и x86_64 различаются?

    connect () заблокирован в течение 3 секунд после успешного завершения соединения ()

    Открыть / прочитать исполняемый файл Unix

    Частая команда «шаблон»: удалить escape-символы расширения параметров

    Передайте мои учетные данные из сеанса ssh в другую сессию ssh

    Как использовать переменные среды OpenVPN для встроенных скриптов?

    Запустите команду перед любой командой терминала

    Статический ip для Virtualbox с использованием мостового соединения

    Прочитать команду интерактивно в цикле for

    Где я могу найти спецификацию, которую должен удовлетворять эмулятор терминала?

    Непрерывный многоадресный трафик с моего маршрутизатора

    Почему LXC-create возвращает ошибку «sudo.conf должен быть 0»?

    Как запустить скрипт, как только изменится номер недели?

    Linux и Unix - лучшая ОС в мире.