Unix команда для выбора лучших значений ребер из сетевого файла - PullRequest
0 голосов
/ 11 марта 2020

У меня есть данные с разделителями табуляции, представляющие сетевые данные (ненаправленные). Среди дублированных ребер я хотел выбрать те ребра, для которых у меня более высокое абсолютное значение значений журнала. Я написал код в python, но это занимает много времени. Буду благодарен, если кто-нибудь поможет мне с командой awk. Обратите внимание, что сеть является ненаправленной, то есть A - B и B - A являются дублирующими ребрами.

Тестовые данные

Gene1   Gene2   Log
AT1G01020   AT1G01010   1.682708
AT1G01020   AT1G01010   -1.90043
AT1G01020   AT1G01010   -1.832192
AT1G01070   AT1G01060   -0.591932
AT1G01070   AT1G01060   -1.204241
AT1G01073   AT1G01070   0.790549
AT1G01060   AT1G01070   1.214972

Expected Output

AT1G01020   AT1G01010   -1.90043
AT1G01070   AT1G01060   1.214972
AT1G01073   AT1G01070   0.790549
gene_table=file1.readlines() # In the real file, j[12]=Gene1, j[13]=Gene2 and j[27]=log value
lfc=[]
for j in gene_table:
    j=j.split("\t")
    j[12]=j[12].strip()
    j[13]=j[13].strip()
    lfc=[]
    int_list=[]
    lfc.append(float(j[27]))
    int_list.append(j[0])
    dict_int={}
    for k in gene_table:
        k=k.split("\t")
        k[12]=k[12].strip()
        k[13]=k[13].strip()
        if (j[0]!=k[0]) and ((j[12]==k[12] and j[13]==k[13]) or (j[12]==k[13] and j[12]==k[13])):
            lfc.append(float(k[27]))
    dict_int=dict(zip(int_list, lfc))
    x=max(lfc, key=abs)
    #print x
    listOfKeys = [key  for (key, value) in dict_int.items() if value == x]
    print listOfKeys

Ответы [ 5 ]

0 голосов
/ 11 марта 2020

Если вам интересно, мой код python выглядел бы так:

d = dict()
with open(filename) as f:
    next(f) # get rid of header line
    for line in f:
        col = line.split()
        key = ' '.join(sorted(col[:2]))
        val = float(col[2])
        d[key] = val if abs(val) - abs(d.get(key, 0)) > 0 else d.get(key, 0)

Результат:

# for k, v in d.items():
#     print(k, v)
# AT1G01010 AT1G01020 -1.90043
# AT1G01060 AT1G01070 1.214972
# AT1G01070 AT1G01073 0.790549
0 голосов
/ 11 марта 2020

Вот решение, похожее на awk по подходу и эффективности, использующее . Он выводит TSV, но вы можете легко изменить программу, если предпочитаете какой-либо другой разделитель или какой-либо другой формат.

# Note: for numbers, jq's length == abs
def MAXAV_BY(stream; k; v):
  reduce stream as $x ({};
    ($x|k) as $key | ($x|v) as $value 
    | if has($key) 
      then if ($value|length) > (.[$key]|length)
           then .[$key] = $value 
           else .
           end
      else .[$key] = $value
      end) ;         

def parse:
  [splits(" +")]
  | (if .[0] < .[1] then .[1] + "\t" + .[0] else .[0] + "\t" + .[1] end) as $k
  | [$k, (.[2] | tonumber)];


MAXAV_BY(inputs | parse; .[0]; .[1])
| keys_unsorted[] as $k
| [($k | splits("\t")), .[$k]]
| @tsv

Вызов

Предполагается, что вышеуказанная jq-программа находится в файле с именем maxav. JQ:

jq -nr -R -f maxav.jq test.txt

Выход

AT1G01020   AT1G01010   -1.90043
AT1G01070   AT1G01060   1.214972
AT1G01073   AT1G01070   0.790549
0 голосов
/ 11 марта 2020

С любым awk в любой оболочке на каждой UNIX коробке:

$ cat tst.awk
BEGIN { FS=OFS="\t" }
NR>1 {
    key = ($1 > $2 ? $1 FS $2 : $2 FS $1)
    max[key] = ( abs(max[key]) > abs($3) ? max[key] : $3 )
}
END {
    for (key in max) {
        print key, max[key]
    }
}

function abs(val) { return (val < 0 ? - val : val) }

$ awk -f tst.awk file
AT1G01070       AT1G01060       1.214972
AT1G01020       AT1G01010       -1.90043
AT1G01073       AT1G01070       0.790549
0 голосов
/ 11 марта 2020

Короткая однострочная строка, использующая GNU datama sh и немного предварительной обработки awk, чтобы превратить A B X в B A X (чтобы получить ожидаемые результаты с большим узлом каждого из них. край первый):

$ awk '$1 < $2 {tmp=$2; $2=$1; $1=tmp} 1' input.txt | datamash -Ws -g 1,2 absmax 3
AT1G01020   AT1G01010   -1.90043
AT1G01070   AT1G01060   1.214972
AT1G01073   AT1G01070   0.790549
0 голосов
/ 11 марта 2020

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

import pandas as pd
df = pd.read_table("file.txt", sep="\s+", header=None)

Добавьте еще три столбца с именами узлов, чтобы устранить неоднозначность bidirectionailyaily и отрицательные журналы:

df['start'] = df[[0,1]].max(axis=1)
df['end'] = df[[0,1]].min(axis=1)
df['abslog'] = df[2].abs()

Найти самые большие журналы абс:

df.sort_values('abslog').groupby(['start','end'])\
                        .last()[[2]]
#                            2
#start     end                
#AT1G01020 AT1G01010 -1.900430
#AT1G01070 AT1G01060  1.214972
#AT1G01073 AT1G01070  0.790549
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...