2014-10-09 2 views
0

Я попытался написать сценарий, который берет по два столбца из нескольких файлов и объединяет их вместе по горизонтали. Проблема в том, что содержимое столбцов находится не в одном порядке в файлах, поэтому данные необходимо сортировать перед конкатенацией.Горизонтальное слияние столбцов из нескольких файлов

Это то, что я придумал до сих пор:

!/bin/bash 

ls *.txt > list 

while read line; do 
    awk '{print $2}' "$line" > f1 
    awk '{print $8}' "$line" > f2 
    paste f1 f2 | sort > "$line".output 
done < list 

ls *.output > list2 

head -n 1 list2 > start 

while read line; do 
    cat "$line" > output 
done < start 

tail -n +2 list2 > list3 

while read line; do 
    paste output "$line" | cat > output 
done < list3 

Мой програмирование, вероятно, не так эффективно, но это не то, что я хочу, чтобы это сделать, за исключением второй последней строки, который не объединяет файлы вместе. Если я вхожу в строку в командной строке, она работает нормально, но в цикле while она пропускает столбцы.

Файлы данных выглядит следующим образом:

bundle_id target_id length eff_length tot_counts uniq_counts est_counts eff_counts ambig_distr_alpha ambig_distr_beta fpkm fpkm_conf_low fpkm_conf_high solvable tpm 
1 comp165370_c0_seq1 297 0.000000 0 0 0.000000 0.000000 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 F 0.000000e+00 
2 comp75418_c0_seq1 1371 852.132325 35 0 0.005490 0.008832 8.287807e-04 5.283100e+00 4.583199e-04 0.000000e+00 2.425095e-02 T 6.225299e-04 
3 comp76235_c0_seq1 1371 871.645349 44 9 43.994510 69.198412 2.002884e+00 3.142003e-04 3.590738e+00 3.516301e+00 3.665174e+00 T 4.877251e+00 
4 comp31034_c0_seq1 379 251.335522 14 0 7.049180 10.629771 1.000000e+00 1.000000e+00 1.995307e+00 0.000000e+00 5.957982e+00 F 2.710199e+00 
5 comp36102_c0_seq1 379 234.689179 14 0 6.950820 11.224893 1.000000e+00 1.000000e+00 2.107017e+00 0.000000e+00 6.350761e+00 F 2.861933e+00 
6 comp26522_c0_seq1 220 0.000000 0 0 0.000000 0.000000 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 F 0.000000e+00 
7 comp122428_c0_seq1 624 0.000000 0 0 0.000000 0.000000 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 F 0.000000e+00 

И мне нужно target_id и столбцы eff_counts.

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

target_id    file_1  file_2  file_3 
comp26522_c0_seq1  0.000000  [number]  [number] 
comp31034_c0_seq1  10.629771  [number]  [number] 
comp36102_c0_seq1  11.224893  [number]  [number] 
comp75418_c0_seq1  0.008832  [number]  [number] 
comp76235_c0_seq1  69.198412  [number]  [number] 
comp122428_c0_seq1 0.000000  [number]  [number] 
comp165370_c0_seq1 0.000000  [number]  [number] 

Edit: Я добавил больше информации примеров. [Число] - это только заполнители; в действительности, они будут числами, подобными строке под файлом_1. Кроме того, заголовок «file_1» будет именем входного файла. И target_id должен быть отсортирован. Все файлы должны содержать одни и те же целевые объекты, но все в другом порядке.

Редактировать два: выход

Я тестировал его с четырьмя файлами и результат выглядит следующим образом:

comp0_c0_seq1 0.000000 
    comp100000_c0_seq1  1.919404 
    comp100002_c0_seq1  2.118776 
    comp100003_c0_seq1  0.072916 
    comp100004_c0_seq1  0.000000 
    comp100005_c0_seq1  0.000000 
    comp100006_c0_seq1  1.548160 
    comp100007_c0_seq1  7.616481 
    comp100008_c0_seq1  0.000000 
    comp100009_c0_seq1  1.374209 

есть пустой столбец слева от первого столбца с данными. И только данные из последнего файла присутствуют.

Благодарим за помощь!

Update:

Я решил вопрос, который я имел со второй последней строкой. Это код, который я использовал:

while read line; do 
    join output "$line" > output2 
    cat output2 > output 
done < list3 

Это выход:

comp0_c0_seq1  0.000000 0.000000 0.000000 0.000000 
comp100000_c0_seq1 1.919404 1.919404 0.000000 1.919404 
comp100002_c0_seq1 2.118776 2.118776 2.225852 2.118776 
comp100003_c0_seq1 0.072916 0.072916 1.228136 0.072916 
comp100004_c0_seq1 0.000000 0.000000 0.000000 0.000000 
comp100005_c0_seq1 0.000000 0.000000 1.982851 0.000000 
comp100006_c0_seq1 1.548160 1.548160 1.902749 1.548160 
comp100007_c0_seq1 7.616481 7.616481 0.000000 7.616481 
comp100008_c0_seq1 0.000000 0.000000 0.000000 0.000000 
comp100009_c0_seq1 1.374209 1.374209 1.378667 1.374209 

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

+0

Вторая часть непонятна. что означает '23'' 0' '100'? – nu11p01n73R

+0

Это числа, которые находятся в столбце eff_counts. В конце концов они должны быть округлены до целого числа, что, вероятно, связано с тем, почему я помещаю эти числа в качестве примера, но в файле они являются поплавками. Это то, что я думал, что могу легко исправить в R, как только у меня появится правильный входной файл. –

+0

В желаемом выводе 23 общее количество eff_counts в файле_1 конкретного target_id? Можете ли вы дать больше строк исходных данных, чтобы получить лучшую картину? – Kokkie

ответ

0

Вы также могли бы начать с коллекцией имен файлов и столбцов, представляющих интерес, как показано ниже, и чем переставлять его с помощью решения, как здесь: Transpose CSV data with awk (pivot transformation)

find . -name "bundle*.txt" -exec awk 'NR>1 {print FILENAME,$2,$8}' {} \; | sed 's/.\//''/' > superbundle.txt 

Объяснение
- найти все файлы с именем, как расслоение *.TXT
- выполнить оператор AWK, который показывает имя файла и столбец 2 и 8 (без заголовка)
- использовать СЭД для удаления ./ из имен файлов

Теперь мы можем использовать «superbundle.txt» и транспонировать используя указанное решение из jaypal.

$ cat transpose.awk 
{ 
    if(!($1 in filenames)) { filename[++types] = $1 }; filenames[$1]++ 
    if(!($2 in target_ids)) { target_id[++num] = $2 }; target_ids[$2]++ 
    map[$1,$2] = $3 
} 
END { 
    printf "%s\t" ,"target_id"; 
    for(ind=1; ind<=types; ind++) { 
     printf "%s%s", sep, filename[ind]; 
     sep = "\t" 
    } 
    print ""; 
    for(target=1; target<=num; target++) { 
     printf "%s", target_id[target] 
     for(val=1; val<=types; val++) { 
      printf "%s%s", sep, map[filename[val], target_id[target]]; 
     } 
     print "" 
    } 
} 

Ниже приведено только три файла, так как я создал только 3 текстовых файла примера.

$ awk -f transpose.awk superbundle.txt | column -t 
target_id   bundle.txt bundle2.txt bundle3.txt 
comp165370_c0_seq1 0.000000 1.000000  0.000000 
comp75418_c0_seq1 0.008832 2.008832  1.008832 
comp76235_c0_seq1 69.198412 3.198412  2.198412 
comp31034_c0_seq1 10.629771 4.629771  3.629771 
comp36102_c0_seq1 11.224893 5.224893  4.224893 
comp26522_c0_seq1 0.000000 6.000000  4.000000 
comp122428_c0_seq1 0.000000 7.000000  4.000000 
+0

Благодарим вас за ввод. Ваше решение выглядит намного элегантнее моего. Это еще не совсем то, что мне нужно. Имена файлов должны входить в заголовок, а числа, принадлежащие каждому файлу, должны располагаться горизонтально, а не вертикально (см. Второй последний блок кода в моем сообщении). Возможно ли это с помощью find/awk? –

+0

Я всегда получаю сообщение об ошибке, но возможно ли что-то подобное? найти . -name "* txt.output" -exec paste {}> output –

0

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

Это может быть не самое эффективное использование bash в местах, но все работает отлично.

ls *.xprs > list 

while read line; do 
    echo "parsing $line" 
    awk '{print $2}' "$line" > f1 
    awk '{print $8}' "$line" > f2 
    paste f1 f2 | sort | head -n -1 > "$line".output 
done < list 

ls *.output > list2 

head -n 1 list2 > start 

while read line; do 
    cat "$line" > output 
done < start 

tail -n +2 list2 > list3 

while read line; do 
    join output "$line" > output2 2>/dev/null 
    cat output2 > output 
done < list3 
sed '1i Contig_ID' list2 | awk '{printf("%s ", $0)}' | sed -e '$a\' | sed 's/.xprs.output//g' > list4 

cat list4 output > results.txt 
+0

Привет, Роджер, я вижу, что это работает, потому что я получаю те же результаты с моим решением. – Kokkie

+0

Hi Kokkie, Спасибо за добавление вашего решения! Я всегда готов узнать новые пути. Соответствуют ли contig_id между файлами? Проблема была в том, что порядок строк был различным в каждом файле, поэтому я использовал сортировку, а затем присоединился. Мне нужно будет подробно рассмотреть ваше решение и посмотреть, смогу ли я понять, как вы решили проблему. –

Смежные вопросы