<- "MKWVTFISLLFLFSSAYSRGVFRRDAHKSEVAHRFKDLGEENFKALVLIAFAQYLQQCPFEDHVKLVNEV
seq TEFAKTCVADESAENCDKSLHTLFGDKLCTVATLRETYGEMADCCAKQEPERNECFLQHKDDNPNLPRLV
RPEVDVMCTAFHDNEETFLKKYLYEIARRHPYFYAPELLFFAKRYKAAFTECCQAADKAACLLPKLDELR
DEGKASSAKQRLKCASLQKFGERAFKAWAVARLSQRFPKAEFAEVSKLVTDLTKVHTECCHGDLLECADD
RADLAKYICENQDSISSKLKECCEKPLLEKSHCIAEVENDEMPADLPSLAADFVESKDVCKNYAEAKDVF
LGMFLYEYARRHPDYSVVLLLRLAKTYETTLEKCCAAADPHECYAKVFDEFKPLVEEPQNLIKQNCELFE
QLGEYKFQNALLVRYTKKVPQVSTPTLVEVSRNLGKVGSKCCKHPEAKRMPCAEDYLSVVLNQLCVLHEK
TPVSDRVTKCCTESLVNRRPCFSALEVDETYVPKEFNAETFTFHADICTLSEKERQIKKQTALVELVKHK
PKATKEQLKAVMDDFAAFVEKCCKADDKETCFAEEGKKLVAASQAALGL"
Proteínas
Composição de aminoácidos
<- seq[seq != "\n"]
seq # operação booleana != significa "não" seq
A seguir, obtém-se o quantitativo de uma letra específica da sequência.
library(stringr)
<- str_count(seq, pattern = "A")
aa aa
[1] 63
str_count
contabiliza apenas a letra “A” na sequência. Dessa forma, é possível obter todos os 20 aminoácidos, repetindo-se esse comando.library(stringr)
<- str_count(seq, pattern = "A")
ala <- str_count(seq, pattern = "R")
arg <- str_count(seq, pattern = "N")
asn <- str_count(seq, pattern = "D")
asp <- str_count(seq, pattern = "C")
cys <- str_count(seq, pattern = "E")
glu <- str_count(seq, pattern = "Q")
gln <- str_count(seq, pattern = "G")
gly <- str_count(seq, pattern = "H")
his <- str_count(seq, pattern = "I")
ile <- str_count(seq, pattern = "L")
leu <- str_count(seq, pattern = "K")
lys <- str_count(seq, pattern = "M")
met <- str_count(seq, pattern = "F")
phe <- str_count(seq, pattern = "P")
pro <- str_count(seq, pattern = "S")
ser <- str_count(seq, pattern = "T")
thr <- str_count(seq, pattern = "W")
trp <- str_count(seq, pattern = "Y")
tyr <- str_count(seq, pattern = "V") val
E, para visualizar o resultado numa tabela:
<- c("Ala", "Arg", "Asn", "Asp", "Cys", "Glu",
aa_3abrev "Gln", "Gly", "His", "Ile", "Leu", "Lys", "Met",
"Phe", "Pro", "Ser", "Thr", "Trp", "Tyr", "Val")
<- c(ala, arg, asn, asp, cys, glu, gln, gly,
aa_quant
his, ile, leu, lys, met, phe, pro, ser, thr, trp,# vetor com o quantitativo de aminoácidos da proteína
tyr, val) <- data.frame(aa_3abrev, aa_quant) # dataframe com os resultados
aa_seq colnames(aa_seq) <- c("Tipo", "Qtde") # renomear as colunas
# Composição de aminoácidos em albumina de soro
# humano
# apresenta a tabela aa_seq
Tipo Qtde
1 Ala 63
2 Arg 27
3 Asn 17
4 Asp 36
5 Cys 35
6 Glu 62
7 Gln 20
8 Gly 13
9 His 16
10 Ile 9
11 Leu 64
12 Lys 60
13 Met 7
14 Phe 35
15 Pro 24
16 Ser 28
17 Thr 29
18 Trp 2
19 Tyr 19
20 Val 43
library(knitr) # para gerar a tabela
::kable(aa_seq, caption = "Composição de aminoácidos em albumina
knitr # de soro humano.", "pipe") # tabela
Tipo | Qtde |
---|---|
Ala | 63 |
Arg | 27 |
Asn | 17 |
Asp | 36 |
Cys | 35 |
Glu | 62 |
Gln | 20 |
Gly | 13 |
His | 16 |
Ile | 9 |
Leu | 64 |
Lys | 60 |
Met | 7 |
Phe | 35 |
Pro | 24 |
Ser | 28 |
Thr | 29 |
Trp | 2 |
Tyr | 19 |
Val | 43 |
<- c("A", "R", "N", "D", "C", "E", "Q", "G", "H", "I", "L", "K", "M",
aa_1abrev "F", "P", "S", "T", "W", "Y", "V")
for (i in aa_1abrev) {
<- str_count(seq, pattern = aa_1abrev)
aa_quant2 return(aa_quant2) # sintaxe opcional para função com apenas uma saída
}
<- data.frame(aa_3abrev, aa_quant2) # dataframe com os resultados
aa_seq colnames(aa_seq) <- c("Tipo", "Qtde") # renomear as colunas
::kable(aa_seq, caption = "Composição de aminoácidos em albumina de soro
knitr humano (uso de loop).", "pipe") # tabela
Tipo | Qtde |
---|---|
Ala | 63 |
Arg | 27 |
Asn | 17 |
Asp | 36 |
Cys | 35 |
Glu | 62 |
Gln | 20 |
Gly | 13 |
His | 16 |
Ile | 9 |
Leu | 64 |
Lys | 60 |
Met | 7 |
Phe | 35 |
Pro | 24 |
Ser | 28 |
Thr | 29 |
Trp | 2 |
Tyr | 19 |
Val | 43 |
str_count
retém em si um loop interno, já que aplica uma função de contagem de elementos a uma sequência, a partir de um padrão pré-definido (o vetor aa_1abrev, no caso). Dessa forma, pode-se simplificar ainda mais o script, não necessitando do loop externo.str_count(seq, pattern = aa_1abrev)
[1] 63 27 17 36 35 62 20 13 16 9 64 60 7 35 24 28 29 2 19 43
<- c(1, 2, 4, 8, 16, 32)
y mean(y)
[1] 10.5
sum(y)
[1] 63
# Tamanho médio estimado de uma proteína a partir do no. de resíduos de
# aminoácidos
<- function(x) {
prot.tamanho <- x * 110 # 'x' representa o número de aminoácidos da proteína
MM return(MM)
}
prot.tamanho(575) # no. de resíduos de aminoácidos de albumina humana
[1] 63250
apply
, composta pelos comandos apply
, sapply
, tapply
, lapply
, e mapply
. Embora possuam processamento mais rápido que funções de loop externo para uso de matrizes muito complexas, cada qual é voltado a um objeto distinto ou situação específica do R (retorno de lista, vetor ou matriz), permite o uso de subset
(subconjuntos de dados), utiliza funções do R ou funções previamente definidas pelo usuário, e roda em apenas uma linha de comando. Essas vantagens contrapõe-se ao uso de loop for aplicado para vetores. Contudo, a vetorização opera muito bem quando se deseja aplicar ou mapear uma função a um vetor/matriz/lista. Quando, por outro lado, se deseja aplicar uma função cujo resultado dependa de mais de um vetor/matriz/lista, o loop for torna-se indispensável, como na titulação de ácidos fracos do capítulo de Aminoácidos.<- aa_seq[4, 2] + aa_seq[6, 2] # AA ácicos
aa_ac <- aa_seq[2, 2] + aa_seq[9, 2] + aa_seq[12, 2] # AA básicos
aa_bas <- aa_seq[14, 2] + aa_seq[18, 2] + aa_seq[19, 2] # AA aromáticos
aa_arom <- aa_seq[10, 2] + aa_seq[11, 2] + aa_seq[15, 2] + aa_seq[1, 2] +
aa_alif 20, 2] # AA alifáticos
aa_seq[<- aa_seq[3, 2] + aa_seq[5, 2] + aa_seq[7, 2] + aa_seq[8, 2] +
aa_pol 13, 2] + aa_seq[16, 2] + aa_seq[17, 2] ## AA polares neutros aa_seq[
<- str_count(seq, pattern = "") # comprimento da sequência
aa_tot <- round(c(aa_ac, aa_bas, aa_arom, aa_alif, aa_pol) / aa_tot * 100) class_perc
E agora, sim, constroi-se a tabela.
<- c("ácido", "básico", "aromático", "alifático", "polar")
aa_class <- data.frame(aa_class, class_perc) # dataframe com os resultados
aa_perc colnames(aa_perc) <- c("Classe", "%") # renomear as colunas
::kable(aa_perc, caption = "Distribuição de classes de aminoácidos
knitr em albumina humana.", "pipe") # tabela
Classe | % |
---|---|
ácido | 16 |
básico | 17 |
aromático | 9 |
alifático | 33 |
polar | 24 |
Tabela de Purificação de Proteínas & R como planilha eletrônica
Para exemplificar a construção de uma planilha simples, tomemos como exemplo uma Tabela de Purificação de Proteínas, usualmente utilizada em Biotecnologia e áreas afins. A forma mais simples de construção de uma planilha envolve 1) a elaboração individual de vetores, e 2) a união dos vetores em uma planilha.
Os procedimentos para purificação (ou isolamento, fracionamento) proteica envolvem técnicas como tratamento químico (precipitação por sulfato de amônio, acetona), tratamento ácido, tratamento térmico, diálise, cromatografia (filtração molecular, troca-iônica, afinidade, fase reversa), entre outros. Para aferição do grau de pureza da amostra obtida utilizam-se normalmente a eletroforese simples, focalização isoelétrica, eletroforese 2D, uso de anticorpos monoclonais, e ensaios de atividade específicos, dentre vários.
Para a tabela de purificação são exigidos somente os vetores de massa de amostra e de atividade enzimática da amostra, obtidos em cada etapa de purificação. Uma planilha simples poderia ser construida como:
# Elaboração de planilha simples de purificação de enzima
# (cada elemento do vetor representa uma etapa de purificação)
# 1. Definição dos vetores principais:
<- c(6344, 302, 145, 34, 10, 3.8) # proteína, mg
prot.total <- c(200, 122, 106, 70, 53, 24) * 1000 # atividade, U
ativ.tot
# 2. Construção da planilha:
<- data.frame(prot.total, ativ.tot)
purif.plan purif.plan
prot.total ativ.tot
1 6344.0 200000
2 302.0 122000
3 145.0 106000
4 34.0 70000
5 10.0 53000
6 3.8 24000
<- cbind(prot.total, ativ.tot)
purif.plan2 purif.plan2
prot.total ativ.tot
[1,] 6344.0 200000
[2,] 302.0 122000
[3,] 145.0 106000
[4,] 34.0 70000
[5,] 10.0 53000
[6,] 3.8 24000
# Edição de nome de colunas
colnames(purif.plan2) <- c("totalProt", "enzAtiv")
purif.plan2
totalProt enzAtiv
[1,] 6344.0 200000
[2,] 302.0 122000
[3,] 145.0 106000
[4,] 34.0 70000
[5,] 10.0 53000
[6,] 3.8 24000
<- data.frame(prot.total, ativ.tot, ativ.tot / prot.total)
purif.plan3 options(digits = 1) # opção para no. de casas decimais
colnames(purif.plan3) <- c("prot.total", "ativ.tot", "ativ.specif")
rownames(purif.plan3) <- c("extr.bruto", "NH4SO2", "acetona",
"Sephadex G-100", "DEAE-celulose", "C8-fase rev")
purif.plan3
prot.total ativ.tot ativ.specif
extr.bruto 6344 2e+05 32
NH4SO2 302 1e+05 404
acetona 145 1e+05 731
Sephadex G-100 34 7e+04 2059
DEAE-celulose 10 5e+04 5300
C8-fase rev 4 2e+04 6316
# Edição simples de planilha (alterações de valores e nomes de colunas)
<- edit(purif.plan3) # ou data.entry( ) purif.plan4
# Importação de dados de outra planilha (CSV):
# 1. Importação com nome da planilha desejada:
<- read.table("planilha.csv", header = T, sep = ",")
purif.plan5
# 2. Importação com tela de busca da planilha desejada:
<- frame <- read.csv(file.choose()) purif.plan5
library(tibble)
<- as_tibble(purif.plan3)
purif.plan6 purif.plan6
# A tibble: 6 × 3
prot.total ativ.tot ativ.specif
<dbl> <dbl> <dbl>
1 6344 200000 31.5
2 302 122000 404.
3 145 106000 731.
4 34 70000 2059.
5 10 53000 5300
6 3.8 24000 6316.
# Tabela de purificação de enzima com pacote 'dplyr':
library(dplyr)
<- mutate(purif.plan, ativ.esp = ativ.tot / prot.total)
purif.plan7 purif.plan7
prot.total ativ.tot ativ.esp
1 6344 2e+05 32
2 302 1e+05 404
3 145 1e+05 731
4 34 7e+04 2059
5 10 5e+04 5300
6 4 2e+04 6316
<- transmute(purif.plan7, ativ.tot = ativ.tot / 1e3)
ativ.tot.kU # vetor de atividade específica em U x 10^3 ativ.tot.kU
ativ.tot
1 200
2 122
3 106
4 70
5 53
6 24
<- mutate(purif.plan7,
purif.plan8 purif = ativ.esp / ativ.esp[1], # nível de purificação
rend.perc = 100 * ativ.tot / ativ.tot[1]
# rendimento percentual
)
# Convetendo à tabela...
library(knitr)
::kable(purif.plan8, caption = "Tabela de purificação para uma enzima", "pipe") knitr
prot.total | ativ.tot | ativ.esp | purif | rend.perc |
---|---|---|---|---|
6344 | 2e+05 | 32 | 1 | 100 |
302 | 1e+05 | 404 | 13 | 61 |
145 | 1e+05 | 731 | 23 | 53 |
34 | 7e+04 | 2059 | 65 | 35 |
10 | 5e+04 | 5300 | 168 | 26 |
4 | 2e+04 | 6316 | 200 | 12 |
library(DT)
<- as.data.frame(purif.plan8)
purif.plan9 rownames(purif.plan9) <- c("extr.bruto", "NH4SO2", "acetona",
"Sephadex G-100", "DEAE-celulose",
"C8-fase rev") # converte a tabela de purificação
# em planilha para se utilizada pelo pacote DT
datatable(purif.plan9) %>% formatRound(1:5, 1) # colunas com 1 casa decimal
::datatable(purif.plan9, editable = "cell") DT
Interação de oxigênio com mioglobina e hemoglobina
\[ y=\frac{pO_2}{K_{50}+pO_2} \tag{1}\]
Por outro lado, o valor de \(K_{50}\) para a hemoglobina é de 26 mmHg, mas sua função exprime-se de forma diferente à da mioglobina:
\[ y=\frac{pO_2^{nH}} {K_{50}^{nH}+pO_2^{nH}} \tag{2}\]
Nessa Equação 2, nH representa o coeficiente de cooperatividade de Hill, que resume a energia distribuida entre as quatro constantes microscópicas de dissociação de O\(_{2}\) aos quatro centros porfirínicos da hemoglobina (grupos heme). Simulando ambas as curvas:
<- 2.8
K50 curve(x / (K50 + x),
xlim = c(0, 100),
xlab = "pO2 (mmHg)", ylab = "y", lty = "dotted"
)
<- 26
K50 <- 2.8
nH curve(x^nH / (K50^nH + x^nH),
xlim = c(0, 100),
xlab = "pO2 (mmHg)", ylab = "y", col = "red",
add = TRUE
# "add" permite adicionar curvas ao gráfico
) abline(0.5, 0, lty = 2) # acrescenta linha de base em meia saturação
\[ y=\frac{K1*L+2*K2*K1*L^2+3*K3*K2*K1*L^3+4*K4*K3*K2*K1*L^4} {4*(1+K1*L+2*K2*K1*L^2+3*K3*K2*K1*L^3+4*K4*K3*K2*K1*L^4)} \tag{3}\]
\[ Ki_{corr} = \frac{i}{N-1+i}*Ki \tag{4}\]
<- c(0.011, 0.016, 0.118, 0.400) # vetor de constantes microscópicas de
K # dissociação de Hb para O2
<- seq(1, 201, 2) # vetor de teores de O2
L
<- c() # inicializa um vetor vazio para saída do vetor corrigido de Ki
Kcorr <- 4 # declara o número de sítios na Hb
N for (i in 1:N) Kcorr[i] <- i / (N - i + 1) * K[i]
# apresenta o vetor de valores de Ki corrigidos para o efeito estatístico Kcorr
[1] 0.003 0.011 0.177 1.600
<- K[1] * L + 2 * K[2] * K[1] * L^2 + 3 * K[3] * K[2] * K[1] * L^3 +
numer 4 * K[4] * K[3] * K[2] * K[1] * L^4
<- 1 + numer
denom <- numer / denom
y plot(L, y, xlab = "pO2", type = "l", col = 2)
# Cálculo de y em cada L
<- function(L, Kcorr) {
Yi <- length(Kcorr)
N <- c()
conc 1] <- L * Kcorr[1]
conc[for (i in 2:N) conc[i] <- conc[i - 1] * L * Kcorr[i]
<- sum((1:N) * conc) / N
numer2 <- 1 + sum(conc)
denom2 return(numer2 / denom2)
}
# Cálculo de y para o vetor de L
<- function(L, Kcorr) {
Y <- c()
YY for (j in 1:length(L)) YY[j] <- Yi(L[j], Kcorr)
return(YY)
}
# Aplicação da função de y para L e gráfico
<- Y(L, Kcorr)
Yfinal plot(L, Yfinal, type = "l", col = 2, xlab = "pO2", ylab = "y")
Alguns pacotes do R para estudo de proteínas
seqinr
vista no capítulo de Aminoácidos, e que computa diversos valores e informações para sequências proteicas, tais como pI, index de hidroxipatia, distribuição de resíduos, entre outros. O sítio do projeto 2 contém informação detalhada para seu uso. Utilizando-se o mesmo procedimento para obtenção da sequência FASTA para a lisozima do capítulo de Aminoácidos (código CAA32175 no sítio NCBI), pode-se obter um conjunto extenso de informações da proteína, como exemplificado abaixo:library(seqinr)
<- c("KVFERCELARTLKRLGMDGYRGISLANWMCLAKWESGYNTRATNYNAGDRSTDYGIFQ
lisozima INSRYWCNDGKTPGAVNACHLSCSALLQDNIADAVACAKRVVRDPQGIRAWVAWRNRCQNRDVRQYVQGCGV")
<- s2c(lisozima) # converte sequência de string de aminoácidos para
seq_liso # o padrão do seqinr (vetor de caracteres)
<- seq_liso[seq_liso != "\n"] # eliminação de espaços exigida pelo
seq_liso2 # seqinr advindos do procedimento de copiar/colar.
seq_liso2
[1] "K" "V" "F" "E" "R" "C" "E" "L" "A" "R" "T" "L" "K" "R" "L" "G" "M" "D"
[19] "G" "Y" "R" "G" "I" "S" "L" "A" "N" "W" "M" "C" "L" "A" "K" "W" "E" "S"
[37] "G" "Y" "N" "T" "R" "A" "T" "N" "Y" "N" "A" "G" "D" "R" "S" "T" "D" "Y"
[55] "G" "I" "F" "Q" "I" "N" "S" "R" "Y" "W" "C" "N" "D" "G" "K" "T" "P" "G"
[73] "A" "V" "N" "A" "C" "H" "L" "S" "C" "S" "A" "L" "L" "Q" "D" "N" "I" "A"
[91] "D" "A" "V" "A" "C" "A" "K" "R" "V" "V" "R" "D" "P" "Q" "G" "I" "R" "A"
[109] "W" "V" "A" "W" "R" "N" "R" "C" "Q" "N" "R" "D" "V" "R" "Q" "Y" "V" "Q"
[127] "G" "C" "G" "V"
pmw(seq_liso2) # peso molecular da proteína
[1] 14701
aaa(seq_liso2) # distribuição de resíduos
[1] "Lys" "Val" "Phe" "Glu" "Arg" "Cys" "Glu" "Leu" "Ala" "Arg" "Thr" "Leu"
[13] "Lys" "Arg" "Leu" "Gly" "Met" "Asp" "Gly" "Tyr" "Arg" "Gly" "Ile" "Ser"
[25] "Leu" "Ala" "Asn" "Trp" "Met" "Cys" "Leu" "Ala" "Lys" "Trp" "Glu" "Ser"
[37] "Gly" "Tyr" "Asn" "Thr" "Arg" "Ala" "Thr" "Asn" "Tyr" "Asn" "Ala" "Gly"
[49] "Asp" "Arg" "Ser" "Thr" "Asp" "Tyr" "Gly" "Ile" "Phe" "Gln" "Ile" "Asn"
[61] "Ser" "Arg" "Tyr" "Trp" "Cys" "Asn" "Asp" "Gly" "Lys" "Thr" "Pro" "Gly"
[73] "Ala" "Val" "Asn" "Ala" "Cys" "His" "Leu" "Ser" "Cys" "Ser" "Ala" "Leu"
[85] "Leu" "Gln" "Asp" "Asn" "Ile" "Ala" "Asp" "Ala" "Val" "Ala" "Cys" "Ala"
[97] "Lys" "Arg" "Val" "Val" "Arg" "Asp" "Pro" "Gln" "Gly" "Ile" "Arg" "Ala"
[109] "Trp" "Val" "Ala" "Trp" "Arg" "Asn" "Arg" "Cys" "Gln" "Asn" "Arg" "Asp"
[121] "Val" "Arg" "Gln" "Tyr" "Val" "Gln" "Gly" "Cys" "Gly" "Val"
AAstat(seq_liso2, plot = TRUE) # gráfico de distribuição, composição
$Compo
* A C D E F G H I K L M N P Q R S T V W Y
0 14 8 8 3 2 11 1 5 5 8 2 10 2 6 14 6 5 9 5 6
$Prop
$Prop$Tiny
[1] 0.3
$Prop$Small
[1] 0.6
$Prop$Aliphatic
[1] 0.2
$Prop$Aromatic
[1] 0.1
$Prop$Non.polar
[1] 0.6
$Prop$Polar
[1] 0.4
$Prop$Charged
[1] 0.2
$Prop$Basic
[1] 0.2
$Prop$Acidic
[1] 0.08
$Pi
[1] 9
# e proporção de resíduos, valor de pI
seqinr
inclui-se a conversão de aminoácidos para abreviações de 1 e 3 letras (a
e aaa
, respectivamente), listagem de 544 propriedades físico-químicas dos 20 aminoácidos proteicos (aaindex
),pK
(autoexplicativo, e visto anteriormente), e cômputo isolado de pI (computePI
) e de massa molecular (pmw
), além de várias outras, tanto para proteômica como para genômica.Outro pacote do R interessante para estudo de proteínas é o Peptides 3, que também computa diversas propriedades físico-químicas para sequências de aminoácidos, além de possibilitar a integração de plotagem com o pacote de dinâmica molecular GROMACS. Como para o
seqinr
, o Peptides
necessita de conversão da sequência em string para o padrão vetorial reconhecido. Entre as funções do pacote destacam-se o cômputo de 66 descritores para cada aminoácido de uma sequência (aaDescriptors
), a composição da sequência por classificação dos resíduos (aaComp
), o cômputo de índice alifático (aIndex
), o índice de hidrofobicidade (hydrophobicity
), índice de instabilidade (instalIndex
), relação de massa/carga (mz
), massa molecular (mw
), e pI (pI
), entre outros.Entre pacotes mais direcionados ao estudo comparativo e visualização de estruturas, bem como para descritores de bioinformática e quimiogenômica vale mencionar
Bio3d
, Autoplotprotein
, protr
, BioMedR
, e UniprotR
, entre muitos.Notas de rodapé
Algumas práticas de programação (Best Codes): 1) organizar um projeto em pastas (ex: dados,figuras,scripts) ou criar um pacote do R como opção; 2) criar seções num código pra facilitar localização; 3) nomear os code chunks (pedaços de código); 4) colocar no início do código as bibliotecas utilizadas, fontes, e chamada de dados (evita procurar algo necessário pro script rodar ao longo do código); 5) identar, preferivelmente com 1 ou 2 comandos por linha; 6) parâmetros de função sempre dentro de função; 7) evitar parâmetros globais; 8) não usar ‘attach’; 8) usar parâmetros com nomes intuitivos (e não x e y; ex: nome_função); 9) atribuir nomes à objetos com uma das três convenções nominais (ex: KiCompet, ki_compet, ki.compet).↩︎
Sítio do projeto Seqinr: http://seqinr.r-forge.r-project.org/↩︎
Pacote Peptides: https://cran.r-project.org/web/packages/Peptides/index.html↩︎