====== Patricia Tachinardi ======
{{:bie5782:01_curso_atual:alunos:trabalho_final:patricia:p1090255.jpg?200|}}
Mestranda do Departamento de Fisiologia do IB-USP, sob orientação da Profa. Gisele Akemi Oda, na área de cronobiologia. Estudo o ritmo de temperatura corporal em tuco-tucos (//Ctenomys// cf. //knighti//), roedores subterrâneos que habitam o noroeste da Argentina.
===== Meus Exercícios =====
[[.:exec]]
===== Proposta de Trabalho Final =====
==== Principal ====
=== Apresentação do problema ===
Actograma é uma forma de representação gráfica muito comum na cronobiologia. É uma ferramenta poderosa para a análise visual de ritmos. Sua inspeção é importante para verificar se a variável medida (atividade locomotora, temperatura corporal, etc.) tem ou não expressão rítmica e, se sim, quais são os padrões que esse ritmo exibe.
O conceito por trás de um actograma é simples. É como se um grande gráfico da série temporal fosse cortado a cada 24 horas e esses gráficos fossem empilhados, de forma que cada linha do novo gráfico corresponda a um dia. É comum plotar actogramas em duplicata (//double plot//), colocando dois gráficos idênticos um ao lado do outro de forma que se possa ver 48 horas em uma única linha, o que facilita muito a visualização de ritmos com períodos diferentes de 24 horas. A figura abaixo mostra o resultado final desse “empilhamento”, na qual a variável medida é a atividade em roda de um tuco-tuco (as barras pretas indicam os momentos que o animal estava ativo). Uma inspeção visual dessa figura nos revela que a atividade em roda desse roedor é rítmica em condições constantes, com um período maior de 24 horas, e sincroniza-se com o ciclo de claro/escuro, quando o animal fica ativo durante a fase de escuro
{{:bie5782:01_curso_atual:alunos:trabalho_final:patricia:actograma.jpg?300|Actograma}}
**Objetivo da proposta:** Fazer uma função no R que retorne esse tipo de gráfico.
=== Plano de execução: ===
**Entrada de dados:**
O formato dos dados a serem utilizados para a construção do actograma pode ser na forma de data frame ou matriz (acho que dependendo dos comandos usados um ou outro pode ser melhor...). Eles devem conter uma coluna com a data, uma com a hora e outra com as medidas da variável. É essencial que os intervalos sejam regulares.
**O que a função deve retornar:**
É essencial que:
- Ela faça gráficos para cada dia da série temporal e depois os empilhe.
- Ela permita que esses gráficos sejam plotados em duplicata (//double plot//)
- Os horários constem no eixo x, e os dias no eixo y.
- Ela permita que sejam selecionados valores máximos e mínimos a serem plotados. Ou seja, caso os dados sejam de temperatura corporal, pode-se selecionar, por exemplo, que apenas os valores entre 36 e 38 graus sejam plotados. Nos horários em que a temperatura não está entre esses valores o gráfico ficaria em branco. Isso é importante porque quando o actograma representa muitos dias é quase impossível observar a amplitude do ritmo, pois as linhas ficam muito pequenas. Deixar os espaços em branco, portanto, facilita muito a visualização
{{:bie5782:01_curso_atual:alunos:trabalho_final:patricia:actograma_basico.png?300|actograma básico}}
Além dessas características básicas, outras funcionalidades facilitariam muito a visualização dos dados e confecção de actogramas para publicação:
- A possibilidade de selecionar, dentro de um data frame ou matriz com muitos dias, quais são aqueles que devem ser plotados no actograma, o que economizaria a criação de objetos intermediários.
- A plotagem dos regimes de iluminação no próprio actograma. Esse tipo de representação facilita muito a interpretação dos dados, especialmente em actogramas muito extensos.
- Um eixo indicando os regimes de iluminação ou outras condições (como diferentes temperaturas ambientes, por exemplo).
{{:bie5782:01_curso_atual:alunos:trabalho_final:patricia:actograma_completo.png?300|}}
== Comentários da Proposta Principal ==
A proposta está ótima. Você tem definido seu input e output, agora pense em cada passo do processo. Acho que a função sem as funcionalidades extras já está de bom tamanho. Legal o argumento que define os máximos e mínimos da variável plotada.
** Gabriel **
==== Plano B ====
=== Apresentação do problema ===
Para identificar a forma da onda de um ritmo é utilizado um gráfico denominado plexograma. É uma forma de representação gráfica na qual são plotadas as médias dos valores obtidos em todos os dias, por horário de medição. Dessa forma, o eixo x tem 24 horas e o y os valores da variável medida. Além de mostrar a forma da onda do ritmo, esse tipo de representação pode ser útil para mostrar relações de fase entre ritmos diferentes, quando são plotados no mesmo gráfico. A figura abaixo mostra um exemplo de medidas de atividade em roda e temperatura corporal feitas em um tuco-tuco. A barra superior mostra o regime de luz, sendo o claro representado pelo branco e o escuro pelo preto.
{{:bie5782:01_curso_atual:alunos:trabalho_final:patricia:plexograma.jpg?450|}}
**Objetivo da proposta:** Criar uma função no R que faça as médias da variável por horário e construa com elas esse tipo de gráfico.
=== Plano de execução ===
**Entrada de dados:** O formato dos dados deve ser o mesmo descrito na proposta principal.
**O que a função deve retornar:**
Uma representação gráfica como a descrita acima, que permita, de preferência:
- A plotagem de mais de uma variável.
- Que seja colocada uma linha horizontal para indicar a média e/ou mediana de todos os dados.
- Que sejam colocadas barras de desvio padrão para cada ponto
- Que seja colocada uma barra com os regimes de iluminação.
Além disso , a função poderia retornar uma tabela com valores numéricos como mediana, média e desvio padrão totais, valores máximo e mínimos e médias máximas e mínimas.
== Comentários ==
Essa idéia é está boa e não é difícil de executar.
** Gabriel **
===== Comentário sobre as funções =====
Eu esbarrei em alguns problemas com a minha proposta principal. Por causa da estratégia que escolhi para empilhar os gráficos, usando layout(),só é possível plotar gráficos correspondentes a no máximo 50 dias. Também por essa razão há pouca flexibilidade para mudar o eixo y.
Terminei essa função, mas como não sabia se ia conseguir, acabei fazendo o plano B também. Pretendo aperfeiçoar ambas para analisar meus dados do mestrado,portanto qualquer sugestão (principalmente em relação a como contornar os problemas da proposta principal) é mais do que bem-vinda.
==== Após a entrega ====
Você avançou muito para o pouco tempo que teve para fazer as funções, muito bom.
Não temos ninguém na equipe que conheça estas análises, mas se o seu foco não desenvolvimento de rotinas, eu buscaria pacotes no R já implementados, para você não começar do zero. Certamente estas funções que vocẽ fez irão te ajudar, mas a coisa parece complexa o suficiente para você aproveitar soluções encontradas por outras pessoas.
===== Função da Proposta Principal =====
==== Página de Ajuda ====
actogram package:nenhum R Documentation
Plotagem de Actogramas
Description:
Produz um gráfico do tipo actograma a partir de séries temporais com intervalos regulares. O gráfico será construído sobre um eixo x de 24 horas.
A plotagem pode ser simples (singleplot) ou em duplicata (doubleplot).
Usage:
actogram(x, intervalo=5, doubleplot=TRUE, lim.max="n", lim.min="n", titulo=NULL, cex=1)
Arguments:
x: Vetor numérico. Valores de uma variável medida em intervalos regulares.
intervalo: Numérico. Valor do intervalo entre medidas, em minutos.
doubleplot: Lógico. Define se a plotagem será em duplicata (doubleplot=TRUE) ou simples(doubleplot=FALSE)
lim.max: Numérico. Valores máximos a serem plotados. Qualquer valor maior que o selecionado não aparecerá no gráfico.
Se lim.max="n" (dafault), o ajuste dos valores que aparecerão no gráfico é automático, para cada dia. Essa opção pode gerar problemas, ver warnings.
lim.min: Numérico. Valores mínimos a serem plotados. Qualquer valor menor que o selecionado não aparecerá no gráfico.
Se lim.max="n" (dafault), o ajuste dos valores que aparecerão no gráfico é automático, para cada dia. Essa opção pode gerar problemas, ver warnings.
titulo: Caracter. Título que aparecerá no topo do actograma. Se titulo=NULL, nenhum título aparecerá.
cex: Numérico. Indica o quanto o tamanho do texto do título e dos eixos deve ser aumento em relação ao default. Para mais detalhes ver o help da função par.
Details:
Cria um gráfico do tipo actograma, em que gráficos para cada dia da série temporal são empilhados, de forma que cada linha
do novo gráfico corresponda a um dia. É possível plotar o actogramas em duplicata (doubleplot),de forma que se possa ver 48 horas
em uma única linha. Os objeto deve ser um vetor numérico, correspondentes a medidas tomadas com intervalos regulares e iniciando à meia-noite.
Value:
Um gráfico do tipo actograma é criado no dispositivo gráfico.
Warning:
Para que a escala do eixo x corresponda aos horários reais, é importante que as medidas que contam nos vetores iniciem à meia-noite.
Esta função não aceita vetores com valores referentes a mais de 50 dias.
Em alguns casos, utilizar os argumentos lim.min="n" e lim.max="n" pode gerar erros. Caso isso aconteça, insira valores numéricos nos argumentos.
Author(s):
Patricia Tachinardi Andrade Silva
p.tachinardi@gmail.com
References:
Moore-Ede M, Sulzman FM, Fuller CA. (1984). The Clocks That Time Us: Physiology of the Circadian Timing System.
Commonwealth Fund Publications. Harvard University Press.446 p.
See Also:
plot() para gráficos genéricos
Examples:
## Dados fictícios, simulando dados obtidos em intervalos de 5 minutos por 15 dias
exemplo= c(rep(c(runif(144, 20, 40), runif(144, 0, 10)), 15))
actogram(exemplo, titulo="Exemplo de Actograma", cex=1.1)
## Dados ficitícios, dimulando dados obtidos em intervalos de 15 minutos por 30 dias
exemplo2= c(rep(c(runif(48, 30, 80), runif(48, 10, 50)), 30))
actogram(exemplo2, titulo="Exemplo de Actograma 2", intervalo=15)
# Agora com limites máximos e mínimos
actogram(exemplo2, titulo="Exemplo de Actograma 2", intervalo=15, lim.min=40, lim.max=80)
## Exemplo com dados reais
# O arquivo "tuco.txt" contem dados da temperatura corporal de um tuco-tuco por 42 dias, com intervalo entre medidas de 5 minutos
tuco= read.table("tuco.txt")
actogram(tuco, titulo="Temperatura corporal", lim.min=36.6, lim.max=37.6, cex=0.8)
==== Código da Função ====
actogram = function(x, intervalo=5, doubleplot=TRUE, lim.max="n", lim.min="n", titulo=NULL, cex=1)
{
med.dia=1440/intervalo # Numero de medidas por dia
if((length(x)/med.dia)>50)
{
cat("\n Erro: o número de dias não pode ultrapassar 50. \n")
}
else
{
x11()
if(doubleplot==FALSE)
{
unico=matrix(nrow=med.dia, ncol=(length(x)/med.dia))
unico[,1]=x[1:med.dia]
for(i in 1:(length(ameg)/med.dia-1)) # Cortando os dados em dias
{
unico[,i+1]= x[((med.dia*i)+1):((med.dia*i)+med.dia)]
}
matriz=matrix(c(1:(ncol(unico))), (ncol(unico)))
layout(matriz, heights=rep(2, nrow(matriz)))
par(mar=c(0,0,0,0), bty="n", lend="butt", oma=c(4,3,4,1), las=1, cex=cex)
if(lim.max=="n"|lim.min=="n")
{
for(i in 1:ncol(unico))
{
plot(unico[,i], type="h", lwd=5, xaxt="n", yaxt="n", ylim= c(lim.min, lim.max))
axis(2, at=(c((max(unico[,i])), min(unico[,i]))), labels=(c(" ", "")))
axis(2, at=( (max(unico[,i]) - min(unico[,i]))/2 + min(unico[,i])), labels=(i), lty="blank")
}
}
else
{
for(i in 1:ncol(unico))
{
plot(unico[,i], type="h", lwd=5, xaxt="n", yaxt="n", ylim=c(lim.min, lim.max))
axis(2, at=(c(lim.min, lim.max)), labels=(c(" ", "")))
axis(2, at=(((lim.max - lim.min)/2)+lim.min), labels=(i), lty="blank")
}
}
axis(1, at=seq(0, med.dia, (60/intervalo*3)), outer=TRUE, labels=seq(0, 24, 3), line=0.5, cex=0.8, xlab="Horas")
title(main=titulo, xlab="Horas", outer=TRUE, ylab="Dias")
}
if(doubleplot==TRUE)
{
duplo=matrix(nrow=med.dia*2, ncol=((length(x)/med.dia)+1))
dia1=x[1:med.dia]
duplo[,1]= c(rep(NA, med.dia), dia1)
dia2=x[((med.dia)+1):((med.dia)+med.dia)]
duplo[,2]=c(dia1, dia2)
dia = matrix(nrow=med.dia, ncol=(length(x)/med.dia))
dia.x = matrix(nrow=med.dia, ncol=(length(x)/med.dia))
for(i in 2:(length(x)/med.dia))
{
dia[,i]=x[(med.dia*(i-1)+1):((med.dia*(i-1))+med.dia)]
dia.x[,i]=x[((med.dia*(i))+1):((med.dia*(i))+med.dia)]
duplo[,i+1]=c(dia[,i], dia.x[,i])
}
matriz.d=matrix(c(1:(ncol(duplo))), (ncol(duplo)))
layout(matriz.d, heights=rep(2, nrow(matriz.d)))
par(mar=c(0,0,0,0), bty="n", lend="butt", oma=c(6,3,5,1), las=1, cex=cex)
if(lim.max=="n"|lim.min=="n")
{
plot(duplo[,1], type="h", lwd=5, xaxt="n", yaxt="n")
for(i in 2:(ncol(duplo)-1))
{
plot(duplo[,i], type="h", lwd=5, xaxt="n", yaxt="n")
axis(2, at=(c((max(duplo[,i])), (min(duplo[,i])))), labels=(c(" ", "")))
axis(2, at=((max(duplo[,i]) - min(duplo[,i]))/2 + min(duplo[,i])), labels=(i-1), lty="blank")
}
plot(duplo[,(ncol(duplo))], type="h", lwd=5, xaxt="n", yaxt="n")
axis(2, at=(c((max(duplo[(1:med.dia),ncol(duplo)])), (min(duplo[(1:med.dia),ncol(duplo)])))), labels=(c(" ", "")))
axis(2, at=((max(duplo[(1:med.dia),ncol(duplo)]) - min(duplo[(1:med.dia),ncol(duplo)]))/2 + min(duplo[,i])), labels=(ncol(duplo)-1), lty="blank")
}
else
{
plot(duplo[,1], type="h", lwd=5, xaxt="n", yaxt="n", ylim=c(lim.min, lim.max))
for(i in 2:(ncol(duplo)-1))
{
plot(duplo[,i], type="h", lwd=5, xaxt="n", yaxt="n", ylim=c(lim.min, lim.max))
axis(2, at=(c(lim.min, lim.max)), labels=(c(" ", "")))
axis(2, at=(((lim.max - lim.min)/2)+lim.min), labels=(i-1), lty="blank")
}
plot(duplo[,(ncol(duplo))], type="h", lwd=5, xaxt="n", yaxt="n", ylim=c(lim.min, lim.max))
axis(2, at=(c((lim.min), lim.max)), labels=(c(" ", "")))
axis(2, at=(((lim.max - lim.min)/2)+lim.min), labels=(ncol(duplo)-1), lty="blank")
}
axis(1, at=seq(0, med.dia*2, (60/intervalo*3)), outer=TRUE, labels=c(seq(0, 24, 3), seq(3, 24, 3)), line=0.5, cex=0.8, xlab="Horas")
title(main=titulo, xlab="Horas", outer=TRUE)
}
}
}
==== Arquivo do Exemplo ====
{{:bie5782:01_curso_atual:alunos:trabalho_final:patricia:tuco.txt|}}
===== Função do Plano B =====
==== Página de Ajuda ====
waveform package:nenhum R Documentation
Gráfico do tipo plexograma (waveform)
Description:
Cria um gráfico do tipo plexograma (waveform) a partir de séries temporais de vários dias, com intervalos regulares,
com a possibilidade de plotar até duas variáveis no mesmo gráfico. Os valores plotados no gráfico são a média dos
valores de todos os dias para cada horário. O eixo x tem 24 horas e o y os valores da variável medida. A função
também retorna um sumário do conjunto de dados (ver seção "Values" para detalhes).
Usage:
waveform(x, y=NULL, intervalo=5, linha="media", limmax.x=NULL, limmin.x=NULL, limmax.y=NULL, limmin.y=NULL, ylab.x=NULL, ylab.y=NULL)
Arguments:
x: Vetor numérico. Valores de uma variável medida em intervalos regulares.
y: Vetor numérico. Valores de uma variável medida em intervalos regulares.
intervalo: Numérico. Valor do intervalo entre medidas, em minutos.
linha: Caracter. Se "media", plota uma linha horizontal correspondente à média da variável. Se "mediana", plota uma linha
correspondente à mediana. Se "n", nenhuma linha é plotada.
limmax.x: Numérico. Limite máximo do eixo y, para o objeto "x".
limmin.x: Numérico. Limite mínimo do eixo y, para o objeto "x".
limmax.y: Numérico. Limite máximo do eixo y, para o objeto "y".
limmin.y: Numérico. Limite mínimo do eixo y, para o objeto "y".
ylab.x: Caracter. Legenda do eixo y para o objeto"x".
ylab.y: Caracter. Legenda do eixo y para o objeto"y".
Details:
É feita uma média, para cada horário, dos valores obtidos em todos os dias e essas médias são plotadas contra um eixo x nos quais contam
os horários. É possível plotar até duas variáveis no mesmo gráfico. Os objetos devem ser vetores numéricos, correspondentes a medidas
tomadas com intervalos regulares e iniciando à meia-noite. O argumento "linha" permite que seja desenhada uma linha com inclinação 0
e intercepto correspondente à média ou mediana da variável.
Value:
Para que a escala do eixo x corresponda aos horários reais, é importante que as medidas que contam nos vetores iniciem à meia-noite.
Um gráfico do tipo plexograma é criado no dispositivo gráfico.
A função também retorna um sumário dos objetos, em formato de lista, na qual:
Média : A média de todos os valores do vetor.
Mediana : Mediana de todos os valores do vetor.
Máximo: Valor máximo dentre todos os valores do vetor.
Mínimo: Valor mínimo dentre todos os valores do vetor.
Média Mínima: A menor média dentre aquelas que aquelas que foram tomadas para os valores de todos os dias, em cada horário.
Fase da Média Mínima: Valor em minutos, correspondente ao horário da média mínima.
Média Máxima: A maior média dentre aquelas que aquelas que foram tomadas para os valores de todos os dias, em cada horário.
Fase da Média Mínima: Valor em minutos, correspondente ao horário da média máxima.
Amplitude: Diferença entre a média máxima e a média mínima.
Warning:
Quando se deseja utilizar a função para duas variáveis, ambas devem ter o mesmo intervalo entre medidas.
Author(s):
Patricia Tachinardi Andrade Silva
p.tachinardi@gmail.com
References:
De Coursey PJ, Pius S, Sandlin C, Wethey D, Schull J. (1998). Relationship of circadian temperature and activity rhythms in two rodent species.
Physiology & Behavior. 65(3):457–463.
See Also:
plot(), para gráficos genéricos
Examples:
## Dados fictícios, obtidos em intervalos de 5 minutos por 15 dias
exemplo= c(rep(c(runif(144, 20, 40), runif(144, 0, 10)), 15))
waveform(exemplo, ylab.x="Exemplo")
## Dados ficitícios, obtidos em intervalos de 15 minutos por 30 dias
objeto1= c(rep(c(runif(48, 30, 80), runif(48, 10, 50)), 30))
objeto2= c(rep(c(runif(48, 70, 140), runif(48, 40, 60)), 30))
waveform(objeto1, objeto2, ylab.x="Objeto 1", ylab.y="Objeto 2", intervalo=15)
# Agora com limites máximos e mínimos
waveform(objeto1, objeto2, ylab.x="Objeto 1", ylab.y="Objeto 2", intervalo=15, limmax.x=130, limmin.x=0, limmax.y=100, limmin.y=0 )
==== Código da Função ====
waveform= function(x, y=NULL, intervalo=5, linha="media", limmax.x=NULL, limmin.x=NULL, limmax.y=NULL, limmin.y=NULL, ylab.x=NULL, ylab.y=NULL)
{
med.dia=1440/intervalo
x11()
resultados=matrix(nrow=288, ncol=(length(x)/med.dia)) # no lugar de 288, colocar medidas.dia
resultados[,1]=x[1:med.dia] # tentar colocar isso no loop... ou não...
for(i in 1:(length(x)/med.dia-1))
{
resultados[,i+1]=x[((med.dia*i)+1):((med.dia*i)+med.dia)]
}
media=apply(resultados, 1, mean)
# Sumario do objeto x
media.total=mean(resultados)
mediana.total= median(resultados)
max.total= max(resultados)
min.total=min(resultados)
max.media=max(media)
hor.max=which(media==max(media))*intervalo
hor.min=which(media==min(media))*intervalo
min.media=min(media)
amplitude= (max.media-min.media)
sumario=list("Média"=media.total, "Mediana"=media.total, "Máximo"=max.total, "Mínimo"=min.total, "Média Mínima"= min.media,"Fase da Média Mínima (em minutos)"= hor.min,
"Média Máxima"=max.media, "Fase da Média Máxima (em minutos)"= hor.max, "Amplitude"= amplitude)
# No caso de só ter objeto x
if(is.null(y))
{
plot(media, xaxt="n", type="l", xlim=c(0,med.dia), ylim=c(limmin.x, limmax.x), xlab="", ylab=ylab.x, bty="n")
axis(1, at=seq(0, med.dia, (60/intervalo*3)), labels=seq(0, 24, 3), line=0.5, cex=0.8)
if (linha=="media")
{
abline(h=mean(resultados))
}
if(linha=="mediana")
{
abline(h=median(resultados))
}
title(xlab="Horas")
return(sumario)
}
# Com objeto x e y
else
{
resultados2=matrix(nrow=med.dia, ncol=(length(y)/med.dia))
resultados2[,1]=y[1:med.dia]
for(i in 1:(length(y)/med.dia-1))
{
resultados2[,i+1]=y[((med.dia*i)+1):((med.dia*i)+med.dia)]
}
media2=apply(resultados2, 1, mean)
# Sumário do objeto y
media.total2=mean(resultados2)
mediana.total2= median(resultados2)
max.total2= max(resultados2)
min.total2=min(resultados2)
max.media2=max(media2)
hor.max2=which(media2==max(media2))*intervalo
hor.min2=which(media2==min(media2))*intervalo
min.media2=min(media2)
amplitude2= (max.media2-min.media2)
sumario2=list("Média"=media.total2, "Mediana"=mediana.total2, "Máximo"=max.total2, "Média Mínima"= min.media2, "Fase da Média Mínima (em minutos)"= hor.min2,
"Média Máxima"=max.media2, "Fase da Média Máxima (em minutos)"= hor.max2 , "Amplitude"= amplitude2)
# Lista com os dois sumarios:
legy= deparse(substitute(y))
legx= deparse(substitute(x))
retorno=list(sumario, sumario2)
names(retorno)=c(legx, legy)
# O Gráfico
par(mar=c(5, 4, 4, 8) + 0.1)
plot(media, xaxt="n", type="l", xlim=c(0,med.dia), ylim=c(limmin.x, limmax.x ), xlab="", ylab= ylab.x, bty="n")
if (linha=="media")
{
abline(h=mean(resultados))
}
if(linha=="mediana")
{
abline(h=median(resultados))
}
par(new=TRUE)
plot(media2, xaxt="n", type="l", xlim=c(0,med.dia), ylim=c(limmin.y, limmax.y),xlab="", ylab="", yaxt="n", bty="n", col="red")
if (linha=="media")
{
abline(h=mean(resultados2), col="red")
}
if(linha=="mediana")
{
abline(h=median(resultados2), col="red")
}
axis(4)
mtext(ylab.y, side=4, line=2.5)
axis(1, at=seq(0, med.dia, (60/intervalo*3)), labels=seq(0, 24, 3), line=0.5, cex=0.8)
title(xlab="Horas")
return(retorno)
}
}