2016-05-11 2 views
1

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

MAPK3 9.49707613464767 9.34083460789419 9.12918870414545 
TIE1 5.12900020712651 5.15008091018047 5.15008091018047 
CYP2C19 3.80757247946463 3.80757247946463 3.87721584865861 
CXCR5 6.40745840005515 6.40745840005515 6.40745840005515 
CXCR5 6.04763929379884 6.13038198258514 6.13038198258514 
DUSP1 12.0320377077951 12.7960658385305 12.625340661444 
MMP10 4.1933379022831 4.1933379022831 4.1933379022831 
RXRG 4.33755505408386 4.32903686336417 4.32903686336417 
RXRG 6.91141485189572 6.96893082690402 6.96893082690402 

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

MAPK3 9.49707613464767 9.34083460789419 9.12918870414545 
TIE1 5.12900020712651 5.15008091018047 5.15008091018047 
CYP2C19 3.80757247946463 3.80757247946463 3.87721584865861 
CXCR5 6.22754884693 6.2689201913201 6.2689201913201 
DUSP1 12.0320377077951 12.7960658385305 12.625340661444 
MMP10 4.1933379022831 4.1933379022831 4.1933379022831 
RXRG 5.6244849529898 5.6489838451341 5.6489838451341 

Если значения Дубликат гена усредняются и заменить исходные данные на образец. Кроме того, я хочу оставить уникальные имена генов и значения нетронутыми. Чтобы быть ясным, я не хочу среднего значения для всей строки, а не для каждого столбца для каждого имени дублирующего гена в столбце 1. Я попытался использовать умные однострочные awk, как описано здесь, calculate and print the average value of strings in a column, и здесь, Average from different columns in shell script. Но мне сложно обобщить команду для учета моих файлов, которые могут содержать до 100 образцов/столбцов. И они беззаботно путают мои уникальные имена генов.

Мои навыки кодирования начального уровня будут смертью меня! Какие-либо предложения?

Благодаря

ответ

1
$ cat tst.awk 
NR == 1 { CONVFMT="%."length($2)-index($2,".")"f" } 
$1 != key { prt() } 
{ 
    key=$1 
    for (i=2 ; i<=NF ; i++) { 
     sum[i] += $i 
    } 
    cnt++ 
} 
END { prt() } 

function prt() { 
    if (key != "") { 
     printf "%s", key 
     for (i=2; i<=NF; i++) { 
      printf "%s%s", OFS, sum[i]/cnt 
     } 
     print "" 
    } 
    delete sum 
    cnt = 0 
} 

$ awk -f tst.awk file 
MAPK3 9.49707613464767 9.34083460789419 9.12918870414545 
TIE1 5.12900020712651 5.15008091018047 5.15008091018047 
CYP2C19 3.80757247946463 3.80757247946463 3.87721584865861 
CXCR5 6.22754884692699 6.26892019132015 6.26892019132015 
DUSP1 12.03203770779510 12.79606583853050 12.62534066144400 
MMP10 4.19333790228310 4.19333790228310 4.19333790228310 
RXRG 5.62448495298979 5.64898384513410 5.64898384513410 
+1

Я нашел, что это именно то, что я искал. Не могли бы вы объяснить код? –

+1

В первой строке указана точность, которую вы используете, основываясь на первом значении в файле, чтобы затем использоваться для каждого другого вычисления. Вторая строка вызывает prt(), когда значение ключа изменяется для печати значений, связанных с предыдущим ключом. Следующий блок (выполняется каждый раз, когда текущий ключ совпадает с предыдущим) суммирует значения для каждого поля и подсчитывает количество строк с этим ключом. Раздел END вызывает prt() для печати значений для последнего считывания ключа. Функция prt() печатает значения. –

1

awk на помощь! Использует украшение/сортировку/декомпозицию, чтобы сохранить порядок строк одинаковым.

$ awk '{f2[$1]+=$2; f3[$1]+=$3; f4[$1]+=$4; c[$1]++; r[$1]=NR} 
    END{for(k in c) print r[k] "\t" k, f2[k]/c[k], f3[k]/c[k], f4[k]/c[k]}' file | 
sort -n | cut -f2 

MAPK3 9.49708 9.34083 9.12919 
TIE1 5.129 5.15008 5.15008 
CYP2C19 3.80757 3.80757 3.87722 
CXCR5 6.22755 6.26892 6.26892 
DUSP1 12.032 12.7961 12.6253 
MMP10 4.19334 4.19334 4.19334 
RXRG 5.62448 5.64898 5.64898 

указать количество десятичных точек вы можете переключиться на printf модификаторы формата.

1

Я новичок в awk, но это может сделать трюк (кажется, работает для меня)

#!/bin/awk -f 

{ 
    for(i = 2; i <= 4; ++i) 
     id[$1][i] = (id[$1][i] * num[$1] + $i)/(num[$1] + 1); 
    ++num[$1] 
} 

END { 
    for(key in num) 
     printf "%s %.15g %.15g %.15g \n", key, id[key][2], id[key][3], id[key][4] 
} 

Выход:

$ cat test.txt|test.awk 
MMP10 4.1933379022831 4.1933379022831 4.1933379022831 
DUSP1 12.0320377077951 12.7960658385305 12.625340661444 
CYP2C19 3.80757247946463 3.80757247946463 3.87721584865861 
TIE1 5.12900020712651 5.15008091018047 5.15008091018047 
CXCR5 6.22754884692699 6.26892019132015 6.26892019132015 
RXRG 5.62448495298979 5.6489838451341 5.6489838451341 
MAPK3 9.49707613464767 9.34083460789419 9.12918870414545 

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

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