эффективное объединение нескольких файлов

sudo update-alternatives --config x-terminal-emulator
1
08.06.2021, 07:52
3 ответа

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

Включите то, что вам нужно, в свой вопрос.

(И извините, знайте, это не так, как обычно, но...)


Это похоже на ваши файлы и требуемый результат?

Вот два примера скриптов. Первый, кто сгенерировал фиктивные файлы:

  • chr1 _A - chr6 _A
  • chr1 _B - chr6 _B
  • chr1 _C - chr6 _C

Отсортировано с помощьюLC_ALL=C sort -k 1b,1

#! /bin/bash
for p in A B C; do
    for i in $(seq 1 6); do
        f="chr${i}_$p"
        printf 'ID %s\n' "$i.$p" >"$f"
        paste <(shuf -n 24 -i 1-222) <(shuf -n 24 -i 0-1 -r) | \
            LC_ALL=C sort -k 1b,1 >>"$f"
    done
done

Предоставление выборочной группы, например:paste chr* | column -t

ID   1.A  ID   1.B  ID   1.C  ID   2.A  ID   2.B  ID   2.C ...
116  1    107  1    101  0    110  1    105  1    111  0   ...
126  1    11   1    105  0    111  1    106  1    117  1   ...
131  1    111  0    106  0    121  0    113  0    121  0   ...
141  0    133  0    110  0    124  0    147  0    145  0   ...
167  1    135  1    113  1    135  0    154  0    146  1   ...
...

Не уверен, что это правильно, решать вам.


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

#! /bin/bash

for PHENO in A B C; do
    join -a1 -a2 -e - -o auto chr1_${PHENO} chr2_${PHENO} >${PHENO}
done

for PHENO in A B C; do
    for n in 3 4 5 6; do
        file="chr${n}_$PHENO"
        join -a1 -a2 -e - -o auto ${PHENO} "$file" >${PHENO}.1
        mv ${PHENO}.1 ${PHENO}
    done
done

В результате получилось три файла A, B и C:

$ paste A B C | column -t
ID   1.A  2.A  3.A  4.A  5.A  6.A  ID   1.B  2.B  3.B  4.B  5.B  6.B  ID   1.C  2.C  3.C  4.C  5.C  6.C
10   -    -    1    1    -    -    101  -    -    1    -    -    1    101  0    -    0    -    -    1
100  -    -    -    0    -    -    102  -    -    -    -    -    0    103  -    -    -    -    -    0
102  -    -    1    -    0    -    105  -    1    0    -    0    -    105  0    -    -    -    -    -
108  -    -    0    -    -    -    106  -    1    -    -    -    1    106  0    -    -    -    1    -
109  -    -    -    -    -    1    107  1    -    -    -    -    -    107  -    -    -    -    -    0
110  -    1    -    -    -    -    109  -    -    -    -    -    0    108  -    -    -    -    -    0
111  -    1    -    -    -    -    11   1    -    -    -    -    -    109  -    -    -    1    0    -
116  1    -    -    -    -    -    111  0    -    -    -    -    -    110  0    -    -    -    -    -
117  -    -    -    -    1    -    113  -    0    -    -    -    -    111  -    0    -    -    -    -

...

# or
# paste <(sort -n A) <(sort -n B) <(sort -n C) | column -t

1
28.07.2021, 11:26

Я бы предложил другой подход:

  1. Убедитесь, что все файлы, такие как chr1_A, содержат полные 15000 записей, отсортированных! Это также включает в себя заполнение «1» там, где оно отсутствует.
  2. Сократите каждый из этих файлов только до столбца «Болезнь».
  3. Создайте файл со столбцом «ID» для каждого PHENO.
  4. Вставить вместо соединения теперь уменьшенные файлы с идентификатором -Столбец один. (Они отсортированы и строки должны совпадать с точки 1)
  5. Создайте сценарий для распараллеливания.

Как:

  1. +2. С помощью скриптаawk-назовите его, например.fillrows.awk

    NR>1 {disease[$1]=$2}
    END {print FILENAME
         for (i=1;i<=15000;i++) {
           if (disease[i]!="")
              {print disease[i] > FILENAME"_red"}
           else {print "1" > FILENAME"_red"}
         }
    }
    

Это сделает файл chr1_Aпохожим на

 ID Disease
 2  0
 5  1

Кchr1_A_red(показано не более 6 строк)

 chr1_A
 1
 0
 1
 1
 1
 1

при выполнении как:awk -f fillrows.awk chr1_A

  1. ID столбца -всегда один и тот же

    { echo ID ; seq 1 15000 ;} > ID_col
    
  2. Склеить вместе -это может быть ограничено в зависимости от оперативной памяти:

    for PHENO in {A..M} ; do
      paste ID_col chr*_$PHENO > $PHENO
    done
    
  3. Некоторые распараллеливания через gnu parallel

     #!/bin/bash
     ##get chrX-Y list without PHENO
     find -name 'chr*' | sed 's/_.$//' | sort -u > chrlist
     parallel awk -f rowfill ::: chr*{A..M}
     { echo ID ; seq 1 15000 ;} > ID_col
     parallel paste ID_col '{1}_{2}_red' '>' '{2}' :::: chrlist ::: {A..M}
    
1
28.07.2021, 11:26

Я придумал рекурсивную функцию для объединения произвольного количества файлов:

join_all() {
    local -a join_opts
    local arg
    while :; do
        arg=$1
        shift
        [[ $arg == '--' ]] && break
        join_opts+=("$arg")
    done

    if (($# == 1)); then
        cat "$1"
    else
        join "${join_opts[@]}" "$1" "$2" | join_all "${join_opts[@]}" -- '-' "${@:3}"
    fi
}


for PHENO in A B C D E F G H I J K L M
do
    files=()
    # use brace expansion to generate the list of files
    files+=( chr{2,3,5,11,14,20,21,22,6,9,13}_${PHENO} )
    files+=( chr{18,8,17}-{1,2}_${PHENO} )
    files+=( chr{1,7,15,16}-{1,2,3}_${PHENO} )
    files+=( chr{19,4,10,12}-{1,2,3,4}_${PHENO} )

    join_all -a1 -a2 -e 1 -o auto -- "${files[@]}" > ${PHENO}
done
1
28.07.2021, 11:26

Теги

Похожие вопросы