Вопрос или проблема
Я хочу отсортировать мой файл, показанный ниже:
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) — это строка, представляющая хромосомы, например,
chr12
,chr17
и т.д. - Вторая (колонка 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
обеспечит точность и последовательность в вашем анализе данных.