Как сортировать столбцы на основе первой строки?

Мне нужно отсортировать столбцы очень большого набора данных (1000 строк и 700000 столбцов). Например, мои столбцы упорядочены случайным образом: col1 col4 col3 col2, и мне нужно их отсортировать.

Я пробовал некоторые команды, но не добился успеха.

пример:

ID M2 M5 M8 M1 M3 M9 .....M7000000 Animal1 1 0 2 1 0 2 .....1 Animal2 0 1 2 0 1 1 .....0 Animal3 2 1 0 1 2 1 .....0 . . . . Animaln 

В этом примере точки означают, что у меня много столбцов и строк. Опять же, мне нужно отсортировать столбцы как:

 ID M1 M2 M3 M4 M5 M6 .....M7000000 Animal1 1 0 2 1 0 2 .....1 Animal2 0 1 2 0 1 1 .....0 Animal3 2 1 0 1 2 1 .....0 . . . . Animaln 

спасибо

  • bash: содержание grepping столбца, которое является динамическим
  • awk, чтобы изменить аналогичные строки
  • Как получить JSON STRING из данной строки
  • Печать последнего элемента каждой строки
  • Шаблоны и обработка файлов
  • Разделение файла на несколько файлов на основе значения 1-го столбца
  • Замена шаблона после n-го совпадения найдена в каждой строке?
  • Измените значения параметра из файла и сгенерируйте файлы параметров из него
  • 8 Solutions collect form web for “Как сортировать столбцы на основе первой строки?”

    С GNU datamash и GNU sort :

     datamash transpose -t ' ' -H <file_in.csv | sort -V | datamash transpose -t ' ' -H >file_out.csv 

    Это отлично подходит для «разумно малых» данных. Он может работать или не работать с вашим файлом.

    Изменить: решения ниже без транспозиций должны быть менее ресурсоемкими.

     perl -pale ' $. == 1 and @I = map { $_->[1] } sort { $a->[0] <=> $b->[0] } map { [ $F[$_] =~ /^M(\d+)$/, $_ ] } 1..$#F; $_ = "@F[0, @I]"; ' yourlargefile 

    1. Для первой строки мы численно сортируем ее 2-й … последние столбцы, используя их числовые части после того, как цифра M встречается в начале, используя хорошо известный Schwartzian maneuver . Это дает нам индексы, упорядоченные так, чтобы столбцы выходили в численном порядке (M1, M2, M3, …)
    2. Остается только использовать эти индексы, исходящие из @I чтобы повторно упорядочить элементы @F .
    3. Присвоение массива в форме с двойными кавычками преобразует его в строку с разделенным пространством элементов.
    4. -p для Perl позволяет автопринт содержимого $_ , -l должен добавить newline .

    Использование модуля perl Сортировать :: Естественно

    входные данные

     ID M2 M5 M8 M1 M3 M9 M700000 A1 m1,2 m1,5 m1,8 m1,1 m1,3 m1,9 m1,7000000 A2 m2,2 m2,5 m2,8 m2,1 m2,3 m2,9 m2,7000000 A3 m3,2 m3,5 m3,8 m3,1 m3,3 m3,9 m3,7000000 A1000 m1000,2 m1000,5 m1000,8 m1000,1 m1000,3 m1000,9 m1000,7000000 
     perl -MSort::Naturally -lane ' if ($. == 1) { @indices = (0, map { $_->[0] } sort { ncmp($a->[1], $b->[1]) } map { [$_, $F[$_]] } 1..$#F ); $, = " "; } print @F[@indices] ' test.data 

    вывод

     ID M1 M2 M3 M5 M8 M9 M700000 A1 m1,1 m1,2 m1,3 m1,5 m1,8 m1,9 m1,7000000 A2 m2,1 m2,2 m2,3 m2,5 m2,8 m2,9 m2,7000000 A3 m3,1 m3,2 m3,3 m3,5 m3,8 m3,9 m3,7000000 A1000 m1000,1 m1000,2 m1000,3 m1000,5 m1000,8 m1000,9 m1000,7000000 

    Если у вас установлена утилита rs , вы можете сделать следующее:

     rs -c' ' -T | { stdbuf -i0 sed "1q" sort -V } | rs -C' ' -T 

    Или все на одной линии:

     rs -c' ' -T | { stdbuf -i0 sed "1q"; sort -V ; } | rs -C' ' -T 
    • Первые rs переносят входные данные (с пространственно разнесенными полями)
    • Командная группа:
      • sed считывает первую строку, выдает ее, затем завершает работу, оставив остальную часть трубы от нетронутой. stdbuf требуется для обеспечения того, чтобы sed только stdbuf до первой новой строки, а не дальше, отключая буферизацию ввода
      • sort оставшиеся строки
    • Второй rs переносит полученный поток обратно в исходный формат.

    rs устанавливается по умолчанию на MacOS. В системах Linux вам, возможно, придется их установить – например

     sudo apt install rs 

    Предостережение: stdbuf и sort -V опция являются специфичными для GNU, поэтому не будут работать с немодифицированным MacOS.

    Если у вас есть GNU awk , вы можете попробовать следующее:

     NR == 1 { for (i = 2; i <= NF; i++) { columns[substr($i, 2)] = i; } count = asorti(columns, sorted, "@ind_num_asc"); printf("%s", $1); for (i = 1; i <= count; i++) { printf(" M%s", sorted[i]); indx[i] = columns[sorted[i]]; } print ""; next; } { printf("%s", $1); for (i = 1; i <= count; i++) { printf(" %s", $(indx[i])); } print ""; } 

    В Python:

     from csv import DictReader, DictWriter with open('in_file.csv') as infile, open('out_file.csv') as outfile: reader = DictReader(infile) writer = DictReader(outfile, fieldnames=sorted(reader.fieldnames)) writer.writerows(reader) 

    Я не знаю, считали ли вы это хорошим ответом, но …

    Почему вы не используете базу данных для решения этой проблемы? вы можете импортировать свой набор данных в качестве временной таблицы, а затем выполнить

    SELECT column1, column2, … column-n FROM my_temp_table

    Вы можете использовать другие фильтры или преобразования по мере необходимости. Затем вы можете переформатировать свой выход по мере необходимости.

    Все эти задачи могут быть запрограммированы как сценарий bash и цепочки выходов с использованием труб.

    Иногда я использовал команду «pv», чтобы увидеть ход выполнения команд.

    Чтобы импортировать набор данных, вы можете запрограммировать ETL с помощью интеграции данных Pentaho.

    Возможно, это тоже поможет вам.

    1. Сначала вы можете использовать транспонирование своего файла (один из https://stackoverflow.com/questions/1729824/an-efficient-way-to-transpose-a-file-in-bash )
    2. Сортировка первого столбца с помощью команды сортировки.
    3. Переставьте снова.

    Пример:

     $ echo "ID M2 M5 M8 M1 M3 M9 .....M7000000 Animal1 1 0 2 1 0 2 .....1 Animal2 0 1 2 0 1 1 .....0 Animal3 2 1 0 1 2 1 .....0 . . . . Animaln" | awk ' { for (i=1; i<=NF; i++) { a[NR,i] = $i } } NF>p { p = NF } END { for(j=1; j<=p; j++) { str=a[1,j] for(i=2; i<=NR; i++){ str=str" "a[i,j]; } print str } }' | sort -n | awk ' { for (i=1; i<=NF; i++) { a[NR,i] = $i } } NF>p { p = NF } END { for(j=1; j<=p; j++) { str=a[1,j] for(i=2; i<=NR; i++){ str=str" "a[i,j]; } print str } }' ID M1 M2 M3 M5 .....M7000000 M8 M9 Animal1 1 1 0 0 .....1 2 2 Animal2 0 0 1 1 .....0 2 1 Animal3 1 2 2 1 .....0 0 1 . . . . Animaln 
    Linux и Unix - лучшая ОС в мире.