У меня есть текстовый файл, подобный следующему:

1 2 3 4 5 6 7 8 9 ... n    <-- column numbering
1 0 0 1 0 0 0 1 0 ... 0
0 1 0 0 0 0 0 0 0 ... 1
1 0 0 0 0 0 0 1 1 ... 0
0 1 1 1 0 1 0 0 0 ... 0
0 1 0 0 1 0 1 0 1 ... 1

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

Что я хочу сделать, это выяснить, какие столбцы, скажем, менее 2 1 с. Например, в моей матрице выше я хотел бы избавиться от столбцов 3, 5, 6 и 7, потому что они имеют только один 1.

Есть ли команда UNIX, чтобы сделать это? Возможно, мне нужна команда Group by-like (SQL), а затем отслеживать, какие столбцы меньше определенного числа, но я не понимаю, как я мог это сделать.

1 ответ1

1

Вы можете использовать awk для обхода матрицы и подсчета количества единиц и нулей, используя следующий скрипт:

count.awk:

NR != 1 {
  for (i=1; i<=NF; ++i)
    count[i] += $i;
}

END {
  ORS = ",";
  for (i=1; i<=length(count); ++i)
    if (count[i] >= min)
       print i
}

Если вы выполните этот скрипт с помощью

awk -v min=2 -f count.awk matrix.txt

вы получите строку столбцов с двумя или более единицами, в данном случае «1,2,4,8,9» (примечание: вы можете изменить min=X на любое минимальное пороговое значение, которое вы хотите).

Теперь используйте команду cut чтобы распечатать только те столбцы, которые нам нужны:

cols=$(awk -v min=2 -f count.awk matrix.txt); cut -d' ' -f${cols:0:-1} matrix.txt

Это хранит вывод awk в переменном (причина этого заключается в том, что awk возвращает список столбцов с , в конце концов. Я "нарезаю" запятую, когда прохожу через cols, чтобы cut).

Установите разделитель для cut на "space" (-d' '), а выходные столбцы - на разделенный запятыми список из awk , при этом последняя запятая будет вырезана (-f${cols:0:-1}).

Выход:

1 2 4 8 9 n
1 0 1 1 0 0
0 1 0 0 0 1
1 0 0 1 1 0
0 1 1 0 0 0
0 1 0 0 1 1

Если вы хотите вывести столбцы с min менее 1 с (т. Е. Столбцы 3, 5, 6, 7), просто измените условие оператора if в приведенном выше сценарии awk на значение if (count[i] < min) .

Выход:

3 5 6 7
0 0 0 0
0 0 0 0
0 0 0 0
1 0 1 0
0 1 0 1

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .