Eu tenho um grande arquivo com duas colunas como esta:
tiago@tiago:~/$ head Ids.txt
TRINITY_DN126999_c0_g1_i1 ENSMUST00000040656.6
TRINITY_DN126999_c0_g1_i1 ENSMUST00000040656.6
TRINITY_DN126906_c0_g1_i1 ENSMUST00000126770.1
TRINITY_DN126907_c0_g1_i1 ENSMUST00000192613.1
TRINITY_DN126988_c0_g1_i1 ENSMUST00000032372.6
.....
e eu tenho outro arquivo com dados, como este:
"baseMean" "log2FoldChange" "lfcSE" "stat" "pvalue" "padj" "super" "sub" "threshold"
"TRINITY_DN41319_c0_g1" 178.721774751278 2.1974294626636 0.342621318593487 6.41358066008381 1.4214085388179e-10 5.54686423073089e-08 TRUE FALSE "TRUE"
"TRINITY_DN87368_c0_g1" 4172.76139849472 2.45766387851112 0.404014016558211 6.08311538160958 1.17869459181235e-09 4.02673069375893e-07 TRUE FALSE "TRUE"
"TRINITY_DN34622_c0_g1" 39.1949851245197 3.28758092748061 0.54255370348027 6.05945716781964 1.3658169042862e-09 4.62597265729593e-07 TRUE FALSE "TRUE"
.....
Estava pensando em usar o sed para fazer uma tradução dos valores da primeira coluna do arquivo de dados, usando o primeiro arquivo como dicionário.
Ou seja, considerando cada linha do arquivo de dadospor sua vez, se o valor da primeira coluna corresponder a um valor da primeira coluna do arquivo de dicionário, será feita uma substituição; caso contrário, a linha seria simplesmente impressa.
Qualquer sugestão seria apreciada.
Respostas:
1 para resposta № 1Você pode transformar seu primeiro arquivo Ids.txt
em um script sed:
$ sed -r "s| *(S+) (S+)|s/^"1/"2/|" Ids.txt > repl.sed
$ cat repl.sed
s/^"TRINITY_DN126999_c0_g1_i1/"ENSMUST00000040656.6/
s/^"TRINITY_DN126999_c0_g1_i1/"ENSMUST00000040656.6/
s/^"TRINITY_DN126906_c0_g1_i1/"ENSMUST00000126770.1/
s/^"TRINITY_DN126907_c0_g1_i1/"ENSMUST00000192613.1/
s/^"TRINITY_DN126988_c0_g1_i1/"ENSMUST00000032372.6/
Isso remove os espaços iniciais e transforma cada linha em um comando de substituição.
Em seguida, você pode usar este script para fazer as substituições em seu arquivo de dados:
sed -f repl.sed datafile
... com redirecionamento para outro arquivo, ou no local com sed -i
.
Se você não tem GNU sed, você pode usar esta versão compatível com POSIX do primeiro comando:
sed "s| *([^ ]*) ([^ ]*)|s/^"1/"2/|" Ids.txt
Isso usa expressões regulares básicas em vez de estendidas e usa [^ ]
para "não espaço" em vez de S
.
1 para resposta № 2
Como o primeiro arquivo (o arquivo de dicionário) é grande, usando sed
pode ser muito lento; uma abordagem muito mais rápida e não muito mais complexa seria usar awk
do seguinte modo:
awk -v col=1 -v dict=Ids.txt "
BEGIN {while(getline<dict){a["""$1"""]="""$2"""} }
$col in a {$col=a[$col]}; {print}"
(Aqui, "Ids.txt" é o arquivo de dicionário e "col" é o número da coluna do campo de interesse no arquivo de dados.)
Essa abordagem também tem a vantagem de não exigir nenhuma modificação no arquivo de dicionário.
0 para resposta № 3
#!/bin/bash
# Declare hash table
declare -A Ids
# Go though first input file and add key-value pairs to hash table
while read Id; do
key=$(echo $Id | cut -d " " -f1)
value=$(echo $Id | cut -d " " -f2)
Ids+=([$key]=$value)
done < $1
# Go through second input file and replace every first column with
# the corresponding value in the hash table if it exists
while read line; do
first_col=$(echo $line | cut -d """ -f2)
new_id=${Ids[$first_col]}
if [ -n "$new_id" ]; then
sed -i s/$first_col/$new_id/g $2
fi
done < $2
Eu chamaria o script de
./script.sh Ids.txt data.txt