сортировка файла по первому столбцу лексически, затем по второму и третьему столбцам численно

Вопрос или проблема

Я хочу отсортировать мой файл, показанный ниже:

chr17   84938   85187   1   100 1
chr12   86723   87265   2   100 1
chr12   87368   87556   11  100 1
chr12   87704   87880   10  100 1
chr12   88018   88256   3   75  1
chr12   88018   88569   1   25  1
chr17   88171   69528   1   100 2
chr12   88393   88569   6   100 1
chr12   88750   88859   3   100 1
chr12   88772   88859   3   100 1
chr12   89019   89674   7   100 1
chr12   89828   90586   1   100 1
chr12   90656   90795   3   100 1
chr17   93459   92763   1   100 2
chr17   96901   69528   4   100 2
chr17   100273  99697   1   100 2
chr16   101557  97558   13  100 2
chr16   103475  101646  8   100 2
chr16   104059  105458  18  100 1
chr16   105550  105776  19  100 1
chr16   105883  106538  17  100 1
chr16   106614  107085  20  100 1
chr18   107887  109384  1   100 1
chr16   108971  108759  2   100 2

Сначала я хочу отсортировать по первому столбцу, затем по второму, а затем по третьему (все в порядке возрастания)

Я сделал это в Microsoft Excel и получил следующий результат:

chr12   86723   87265   2   100 1
chr12   87368   87556   11  100 1
chr12   87704   87880   10  100 1
chr12   88018   88256   3   75  1
chr12   88018   88569   1   25  1
chr12   88393   88569   6   100 1
chr12   88750   88859   3   100 1
chr12   88772   88859   3   100 1
chr12   89019   89674   7   100 1
chr12   89828   90586   1   100 1
chr12   90656   90795   3   100 1
chr16   101557  97558   13  100 2
chr16   103475  101646  8   100 2
chr16   104059  105458  18  100 1
chr16   105550  105776  19  100 1
chr16   105883  106538  17  100 1
chr16   106614  107085  20  100 1
chr16   108971  108759  2   100 2
chr17   84938   85187   1   100 1
chr17   88171   69528   1   100 2
chr17   93459   92763   1   100 2
chr17   96901   69528   4   100 2
chr17   100273  99697   1   100 2
chr18   107887  109384  1   100 1

Я использовал в командной строке Unix эту команду

sort -k 1,1 -nk2 -nk3 file.txt

Это дало мне:

chr17   84938   85187   1   100 1
chr12   86723   87265   2   100 1
chr12   87368   87556   11  100 1
chr12   87704   87880   10  100 1
chr12   88018   88256   3   75  1
chr12   88018   88569   1   25  1
chr17   88171   69528   1   100 2
chr12   88393   88569   6   100 1
chr12   88750   88859   3   100 1
chr12   88772   88859   3   100 1
chr12   89019   89674   7   100 1
chr12   89828   90586   1   100 1
chr12   90656   90795   3   100 1
chr17   93459   92763   1   100 2
chr17   96901   69528   4   100 2
chr17   100273  99697   1   100 2
chr16   101557  97558   13  100 2
chr16   103475  101646  8   100 2
chr16   104059  105458  18  100 1
chr16   105550  105776  19  100 1
chr16   105883  106538  17  100 1
chr16   106614  107085  20  100 1
chr18   107887  109384  1   100 1
chr16   108971  108759  2   100 2

Что я могу сделать здесь, чтобы получить вывод, аналогичный Excel?

sort -k 1,1 -nk2 -nk3 file.txt

то же самое, что и:

sort -k 1,1 -n -k 2 -n -k 3

Фактически эквивалентно:

sort -n -n -k 1,1 -k 2 -k 3

Или:

sort -k 1,1 -k 2 -k 3 -nn

Опция -n меняет критерий сортировки по умолчанию с лексического на числовой глобально. Не имеет значения, где в командной строке появляется опция (при условии, что вы не используете другие опции, которые меняют критерии сортировки), и указание ее более одного раза не имеет значения.

chr17 или chr12, не являющиеся числами, рассматриваются как номер 0 с точки зрения числового сравнения (и 17chr будет рассматриваться как 17; sort попытается интерпретировать строку как число с начала строки, пропуская ведущие пробелы и игнорируя все, что находится за пределами того, что можно интерпретировать как число).

Также обратите внимание, что -k 2 это -k 2,end-of-the-line, так что на первой строке, например, то, что будет сравниваться (ключ сортировки) это " 84938 85187 1 100 1" (включая ведущие пробелы). С -n это эквивалентно -k2b,2, где ключ сортировки будет "84938", но только потому, что ведущие пробелы и все, что после первого числа, игнорируются, когда этот ключ сортировки интерпретируется как число¹.

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

sort -b -k 1,1 -k 2,2n -k 3,3n

Здесь также добавление -b для обрезки ведущих пробелов из ключей сортировки глобально.

Теперь, в лексическом сравнении, как это делается для первого ключа, будьте осторожны, что chr2 сортируется после chr19. Так что, предполагая, что первое поле всегда начинается с chr, вы могли бы сортировать численно глобально, но с ключами, указанными как:

sort -nb -k 1.4,1 -k 2,2 -k 3,3

То есть с первым ключом, который является частью первого поля, начиная с 4й позиции, интерпретируемой как nумерный, как и другие два ключа сортировки.

GNU-реализация sort также имеет опцию -V и ключ сортировки V для сортировки по Vерсии, которая работает со строками, содержащими числа. Здесь:

sort -b -k 1,1V -k 2,2n -k 3,3

В локалях, где пробелы игнорируются в первой инстанции,

sort -V -k 1,3

С частью строки от начала до конца 3го поля как единственным ключом сортировки k, но интерпретируемым как Vерсия, это даже сработает.


¹ Но будьте осторожны, некоторые локали могут иметь символ, классифицируемый как пробел, в качестве разделителя тысяч, что может помешать здесь.

Ответ или решение

Для решения задачи сортировки файла по первой колонке в лексическом порядке, а затем по второй и третьей колонкам в числовом порядке, существует несколько подходов как в Microsoft Excel, так и в среде Unix/Linux. В данной инструкции будет рассмотрен эффективный способ сортировки с использованием команды sort в Unix, а также определены возможные причины, по которым результат может отличаться от вывода в Excel.

Понимание данных

В вашем файле представлены следующие колонки:

  1. Первая колонка (колонка 1) — это строка, представляющая хромосомы, например, chr12, chr17 и т.д.
  2. Вторая (колонка 2) и третья (колонка 3) колонки содержат числовые данные, которые требуется отсортировать в числовом порядке.

Проблема с сортировкой

При использовании команды sort -k 1,1 -nk2 -nk3 file.txt, происходит сортировка по первой колонке в лексическом порядке (что корректно), но при этом сортировка по второй и третьей колонкам выполняется глобально в числовом формате. Это может привести к непредсказуемым результатам, когда, например, ‘chr2’ окажется после ‘chr19’, что противоречит желаемому порядку.

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

Правильная команда сортировки

Для получения эквивалентного вывода, как в Excel, необходимо изменить команду на следующую:

sort -b -k 1,1 -k 2,2n -k 3,3n file.txt

Вот что делает каждая часть этой команды:

  • -b — игнорировать ведущие пробелы.
  • -k 1,1 — сортировка по первой колонке в лексическом порядке.
  • -k 2,2n — сортировка по второй колонке в числовом порядке.
  • -k 3,3n — сортировка по третьей колонке в числовом порядке.

Таким образом, эти ключи заставят sort сначала рассмотреть первый столбец, а в случае совпадений — сравнить значения во втором столбце, а затем в третьем.

Альтернативные способы

Если необходимо учитывать специфику строк, содержащих комбинации чисел и букв, можно использовать флаг версии -V. Например:

sort -b -k 1,1V -k 2,2n -k 3,3n file.txt

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

Заключение

Убедитесь, что используемые вами команды соответствуют требованиям к сортировке. С помощью изложенных подходов вы сможете получить вывод, аналогичный тому, что был получен в Excel, без потери точности в числовых значениях. Не забывайте также учитывать специфику используемой локали, где разделители и пробелы могут влиять на результат сортировки. Правильное использование параметров команды sort обеспечит точность и последовательность в вашем анализе данных.

Оцените материал
Добавить комментарий

Капча загружается...