Хотя lsblk
представил /dev/sda3
с размером 58,8 ГБ, это размер раздела, а не физического тома LVM. Таким образом, LVM не может видеть дополнительное пространство. Поскольку раздел имеет правильный размер, необходимо изменить размер двух вещей :: физического тома и корневого логического тома :
pvresize /dev/sda3
lvextend -l +100%FREE /dev/c1/root
Другой awk
подход. Этот будет печатать NA
для случаев, когда конкретный вариант отсутствует в одном из входных файлов :
awk '{ if(FNR==1){files[fnum++]=FILENAME}else{var[$1"\t"$2][FILENAME]=$3}} END{ for(v in var){for(file in files){if(! var[v][files[file]]){var[v][files[file]]="NA"}}}printf "chr\tposition "; for(i=1;i<=fnum;i++){printf "value-samp%s\t",i;} print "";for(v in var){ printf "%s ",v; for(file in var[v]){if(file in var[v]); else{var[v][file]="NA";} printf "%s\t", var[v][file] } print ""}}' s1 s2
Или, если вам не нравится вся эта краткость:
awk '{
if(FNR==1){
files[fnum++]=FILENAME
}
else{
var[$1"\t"$2][FILENAME]=$3
}
}
END{
for(v in var){
for(file in files){
if(! var[v][files[file]]){
var[v][files[file]]="NA"
}
}
}
printf "chr\tposition ";
for(i=1;i<=fnum;i++){
printf "value-samp%s\t",i;
}
print "";
for(v in var){
printf "%s ",v;
for(file in var[v]){
if(file in var[v]);
else{
var[v][file]="NA";
}
printf "%s\t", var[v][file];
}
print "";
}
}' s1 s2
Измените s1
и s2
на фактические имена файлов, которые вы используете. Выполнение вышеуказанного на вашем примере ввода возвращает:
chr position value-samp1 value-samp2
1 3774318 1 NA
1 3775200 2 1
1 3774319 1 NA
1 3775201 7 1
1 3775202 70 10
1 3775203 7 1
1 3775204 270 12
1 3775205 3 1
1 3775206 5 13
1 3775207 NA 1
1 3775208 NA 1
1 3775209 NA 18
Взяв это решение аналогичной проблемы за основу, нам нужно будет его тонко настроить, чтобы получить то, что вы хотите. Это не ответ, а просто набросок, и в нем используется какой-то псевдокод(sic? ), чтобы обрисовать в общих чертах, что должно быть сделано.
Обзор команды Linux join и ее возможностей необходим для успешного решения. Обратите внимание, что сортировка каждого входного файла по порядку в определенном поле (здесь с использованием номера хромосомы, поле 2 )перед объединением имеет важное значение.
Так как объединение может объединять только два файла, нам потребуется выполнить объединение несколько раз, поэтому потребуется определенная структура программирования и механизм управления. Нам также нужно будет изменить сами данные, так как вы указали пустые (нулевые )значения, которые следует заменить на 0.
1 )Скопируйте первый файл данных под другим именем, возможно, samp _0
2 )Проверьте каждую строку samp _0 на наличие значения поля 3. Если ноль, замените на 0.
3 )Инициализируйте значение x , чтобы оно соответствовало номеру файла данных.
4 )Создайте цикл for/next для последовательного использования каждого файла данных. Сколько файлов данных у вас есть? Ну, чтобы это работало без редактирования сценария каждый раз, когда вы его запускаете, запустите сценарий, пока не закончатся файлы данных с циклом for/next.
5 )Внутри цикла for/next сделайте две вещи.
5A )Проверить каждую строку следующего файла на наличие значения поля 3. Если ноль, заменить на 0.
5B )выполнить соединение включая непарные линии (с опцией-a )в поле номера хромосомы (2 )файла samp _0 и файл samp _x с автоматическим форматированием (с использованием опции-o auto ), поэтому он объединяет строки данных для всех хромосом, а не только те, у которых есть данные как в файле samp _0 , так и в файле samp _x . Запишите вывод в файл samp _0 .
6 )Если есть другой файл данных, увеличьте значение x , затем вернитесь и повторите 3 ). Если все файлы данных были объединены, выйдите из цикла for/next, потому что вы закончили.
Я проигнорировал chr
на данный момент, потому что, если он всегда равен 1, его можно безопасно игнорировать, иначе ОП должен объяснить, как он вписывается.
awk 'BEGIN {printf "position " }
FNR>1{
if (FNR==2) {nof+=1; printf ("%s%s ","Sam", nof )};
pos[$2]=$2; data[$2, nof]=$3}
END { printf "\n"; for (p in pos) {printf ("%s ", pos[p]);
for (d=1;d<=nof;d++) printf ("%s ", data[p,d]+0); print "\n"}
}' file1 file2 | column -t
Выход
position Sam1 Sam2
3774318 1 0
3774319 1 0
3775200 2 1
3775201 7 1
3775202 70 10
3775203 7 1
3775204 270 12
3775205 3 1
3775206 5 13
3775207 0 1
3775208 0 1
3775209 0 18
Прохождение
Печатать заголовок первого столбца при запуске
awk 'BEGIN {printf "position " }
Игнорировать все первые строки как заголовки
FNR>1{
Во 2-й строке каждого файла увеличьте количество файлов и напечатайте заголовок
if (FNR==2) {nof+=1; printf ("%s%s ","Sam", nof )};
Для каждой строки после заголовка поместите позицию в массив pos
; установить другой массив data
, содержащий значение sam
, проиндексированное pos
и номер файла (выборки )
pos[$2]=$2; data[$2, nof]=$3}
После считывания всех файлов напечатайте newline
в заголовках, затем повторите pos
печать каждой позиции
END { printf "\n"; for (p in pos ) {printf ("%s ", pos[p]);
Затем выполните итерацию по индексу массива data
по номерам p
и sam
/file, добавляя 0 к любым нулевым значениям data
, чтобы что-то печаталось даже при отсутствии данных; затем напечатайтеnewline
for (d=1;d<=nof;d++) printf ("%s ", data[p,d]+0); print "\n"}
Только входные файлы и вывод вывода через column
, чтобы он выглядел красиво
}' file1 file2 | column -t
Добавлен chr в предположении, что это другой индекс
awk 'BEGIN {printf "chr position " }
FNR>1{
if (FNR==2) {nof+=1; printf ("%s%s ","Sam", nof )};
chr[$1]=$1; pos[$2]=$2; data[$1, $2, nof]=$3}
END { printf "\n"; for (c in chr) {for (p in pos ) {printf ("%s %s ", chr[c], pos[p]);
for (d=1;d<=nof;d++) printf ("%s ", data[c, p, d]+0); print "\n"}
}}' file1 file2 | column -t
Я использую другой подход, больше в стиле SQL, если можно так сказать. У меня есть только основная идея и некоторые детали. Идея состоит в том, чтобы использовать «нормализованный» список, т.е. сначала добавить идентификатор источника -в одну большую общую таблицу :
.У меня есть образцы файлов с ch.s1
по ch.sn
; Я беру «chr» и «pos» в качестве первичного ключа.
. chr.sh >ch.tmp
for f in ch.s?
do
cat $f | while read l
do
echo "$l $f"
done
done
Итак, теперь это один большой файл с 4-м столбцом, исходный (файл ). Для простоты я использовал временный файл.
Отсюда идет «тройник»:
Чтобы получить список источников для коммун, вы можете сделать:
]# grep -o "ch.s.*" ch.tmp | sort | uniq -c
3 ch.s1
4 ch.s2
2 ch.s3
(-c
могут дать ценную информацию; Я использую grep -o
, потому что я напутал с разделителями(cut
считает каждый пробел?? )). Это всего лишь один из способов получить этот список, но напрямую из данных. Это инвестиции.
Этот отсортированный список является заголовком и может использоваться для заполнения таблицы.
И подготовить отчет о том большом столе:
]# sort ch.tmp -k1,2 -k4
1 16 A ch.s1
1 256 B ch.s1
1 333 dD ch.s2
1 4096 A ch.s1
1 4096 DD ch.s2
1 4096 A ch.s3
2 333 Dd ch.s2
2 777 x ch.s2
3 6666 F ch.s3
Эта сортировка является единственной большой операцией. -Я рассчитываю на ее эффективность во всех ситуациях.
После этих двух приготовлений остается немного зацикливания, но только очень "локально" :для каждой строки данных вы только перебираете в цикле фиксированное количество столбцов, ставя "значение" или "ноль".
Если вы возьмете эту часть:
1 4096 A ch.s1
1 4096 DD ch.s2
1 4096 A ch.s3
...это показывает, как строки готовы к печати одна за другой, почти. Нет необходимости в полном поиске (цикла -в -цикле -).
С элегантным способом «тройника» отch.tmp
(унифицированной таблицы )к «группе по источнику», т.е. grep -o
и sort -k...
, этот подход должен быть готов также для «больших» данных. Тем более, что шаги можно регулировать.
Он имитирует чтение в таблицу SQL, а также отчетную часть в виде сводной таблицы.
Каков реалистичный сценарий сравнительного анализа?
20 файлов примеров по 50 КБ каждый,с небольшим перекрытием, как в ОП?
С Perl, а также с awk, я думаю, вы можете сделать этот подход очень легко. Со сценарием bash я не знаю, из-за производительности массива; с bash вы можете использовать файл tmp, как в моем плане.
С помощью Миллера(https://github.com/johnkerl/miller)вы можете запустить
mlr --c2p --ifs ' ' --repifs \
sort -f chr,position,value \
then nest --implode --values --across-records -f value \
then nest --explode --across-fields --values -f value \
then unsparsify then clean-whitespace input0*.csv >output.csv
И получить
chr position value_1 value_2
1 3774318 1 -
1 3774319 1 -
1 3775200 1 2
1 3775201 1 7
1 3775202 10 70
1 3775203 1 7
1 3775204 12 270
1 3775205 1 3
1 3775206 13 5
1 3775207 1 -
1 3775208 1 -
1 3775209 18 -
Примечание:
input0*.csv
--c2p
на --csv
.