Este documento é um guia abrangente sobre os fundamentos da programação em R, com foco em conceitos-chave e suas aplicações, especialmente no campo da saúde.
2.1.1 Boas práticas gerais
É importante criar um guia de estilos para a execução tanto de projetos individuais como em equipa para garantir consistência. Isto tem alguns benefícios:
1. Criar interoperabilidade: Os dados podem ser combinados e comparados através do tempo e em locais diferentes.
2. Melhoria na interpretação: Manter estruturas de código, nomenclatura e de projetos permite que quando colegas e nós próprios olhamos para um projeto consigamos rapidamente verificar erros e oportunidades de melhoria.
3. Reprodutibilidade: Algo que será o foco do Módulo 7 mas que implica que os nomes dos ficheiros, pastas e variáveis sejam coerentes, pois a ausência dos mesmos limita a gestão de dados ou a análise possa ser replicada no futuro.
Em termos individuais, este tipo de guias deve ser criado antes da criação de um projeto.
Nota
O nosso guia pessoal pode mudar ao longo do tempo, mas se seguir princípios claros logo de ínicio ajuda a direcionar a nossa jornada em Data Science
2.1.2 Organização de um projeto
2.1.2.1 O que é um projecto?
Um projeto em R é, fundamentalmente, uma maneira estruturada de organizar os arquivos, códigos, dados e resultados relacionados de uma análise ou conjunto de análises.
2.1.2.2 Características de um Projeto R
Pasta dedicada: Um projeto R tem a sua própria pasta Este pasta contém todos os arquivos relevantes, como scripts de R, dados, documentos de R Markdown, e qualquer outro recurso necessário.
Isolamento do Ambiente de Trabalho: Cada projeto em R tem próprio ambiente de trabalho. Isso significa que as variáveis, e configurações são específicos para o projeto e não afetam outros projetos ou a sessão global do R.
Gerir de Pacotes e Dependências: Projetos R podem gerir as suas próprias bibliotecas de pacotes, garantindo que as análises sejam reproduzíveis com as versões corretas dos pacotes usados.
Facilita a Colaboração: Ter todos os componentes de uma análise numa unica pasta facilita a partilha do projeto com colegas ou para fins de publicação, como em repositórios online (e.g., GitHub).
2.1.2.3 Benefícios de Usar Projetos R
Organização: Mantém seu trabalho organizado e estruturado.
Reprodutibilidade: Facilita a reprodução e a continuidade do trabalho.
Colaboração Eficiente: Torna mais fácil colaborar com outros e partilhar seu trabalho.
2.1.2.4 Criar um projecto
Abrir o RStudio e selecionar “File” > “New Project” no menu.
Escolher entre criar um novo diretório para o projeto ou usar um diretório existente.
Dar um nome ao Projeto e escolher a localização para o diretório do projeto no seu computador. É importante ser consistente e definir sempre a mesma pasta que terá todos os seus projecto.
Clicar em “Create Project”. Isso criará uma nova pasta com um arquivo .Rproj, que é o arquivo do projeto RStudio. Deve clicar no “Open in new session” para que abra numa nova sessão de R. Como exemplificado na Figura 2.1
2.1.2.5 Organização do projecto
O projecto deve seguir um padrão comum em projetos de análise de dados, especialmente projetos que utilizam R.
Código
my_project│├── documentation # Pasta para documentação do projeto│├── output # Pasta para armazenar saídas do projeto, incluindo:│ ├── figures # - Gráficos e figuras gerados pelas análises│ ├── tables # - Tabelas resultantes das análises│ └── documents # - Documentos, relatórios ou apresentações│├── data # Pasta para os dados utilizados no projeto, subdividida em:│ ├── raw # - Dados brutos, como originalmente recebidos│ └── processed # - Dados processados ou modificados usados nas análises│├── README.md # Arquivo Markdown com informações sobre o projeto (descrição, instruções, etc.)│├── script.qmd # Script de análise ou relatório em Quarto (Quarto Markdown)│└── my_project.Rproj # Arquivo do projeto RStudio, facilita a gestão do ambiente de trabalho e configurações
Aviso
Quando queremos voltar a tabalhar no nosso projecto é fundamental abrir sempre pelo ficheiro my_project.Rproj
Este é dos erros mais comuns de utilizadores inexperientes!
Só assim é que estamos a trabalhar no projecto e as alterações são guardadas.
2.1.3 Organização do R Studio
O RStudio é em várias áreas principais, conhecidas como paineis, cada um com sua própria função específica, como descrito na Figura 2.2:
1. Painel Consola
Localização: Normalmente na parte inferior (ou superior que é a minha preferencia) esquerdo.
Função: Onde o código R é executado interativamente, pode escrever os comandos R diretamente aqui e ver os resultados imediatamente. É também onde as mensagens do sistema e erros são exibidos.
2. Painel Script
Localização: Geralmente na parte superior (ou inferior que é a minha preferencia) esquerda.
Função: Este painel é um editor de texto onde você pode escrever e editar scripts R (.R). Os scripts podem ser guardados e organizados em projetos.
3. Painel Environment/History
Localização: Normalmente na parte superior direita.
Função: Este painel tem duas abas principais:
Environment: Mostra os objetos (datasets, variáveis, funções) carregados na memória do R.
History: Mantém um registro dos comandos previamente escritos na consola.
4. Painel de Arquivos/Plots/Packages/Help/Viewer
Localização: Geralmente na parte inferior direita.
Função: Este painel multifuncional contém várias abas:
Files: Permite explorar os ficheiros e pastas.
Help: Fornece acesso à documentação e ajuda de funções e pacotes R.
Viewer: Onde se vê o resultado dos outputs.
O RStudio é altamente personalizável, permitindo organizar os painéis de acordo com as preferências ou as necessidades do projeto.
2.1.4 Nomes de ficheiros
Ao nomear ficheiros em projetos de Data Science, é crucial que os nomes sejam informativos, claros e consistentes.
Isso ajuda a manter a organização e facilita o entendimento e a localização dos ficheiros por qualquer pessoa que esteja a trabalhar no projeto. Abaixo estão algumas boas práticas:
Nomes Descritivos e Claros: Utilize nomes que descrevam claramente o conteúdo do arquivo. Evite nomes genéricos como “data.csv” ou “análise_final.R”.
Evitar Informações Pessoais: Não inclua informações pessoais nos nomes dos arquivos, especialmente em projetos compartilhados ou públicos.
Uso de Underlines ou Hifens: Evite espaços nos nomes dos arquivos. Prefira underlines (_) ou hifens (-) para separar palavras.
Limitação do Número de Caracteres: Mantenha os nomes concisos para facilitar a leitura e o manuseio dos arquivos, especialmente em sistemas com limites de caracteres para caminhos de arquivos.
Formato de Data: Use o formato ISO 8601 para datas nos nomes dos arquivos (YYYYMMDD). Isso padroniza a representação de datas e evita ambiguidades.
Versões Explícitas: Se o arquivo tem várias versões, indique claramente a versão no nome, como v01, v02, ou para detalhes mais específicos, v01.01, v01.02, etc.
Clareza nas Abreviaturas: Use abreviaturas que sejam compreensíveis para todos os membros da equipe. Evite jargões ou abreviações muito específicas sem uma explicação adequada.
Separação de Dados Brutos e Manipulados: Mantenha uma distinção clara entre dados brutos (raw) e dados processados ou manipulados, possivelmente em pastas distintas como data_raw e data_processed.
Organização em Pastas: Organize projeto com pastas.
Documentação Associada: Se possível, inclua um arquivo README na pasta, explicando a estrutura de arquivos e pastas, especialmente se o projeto for complexo ou partilhado com uma equipa.
Seguir estas práticas na nomeação e organização de arquivos contribui significativamente para a eficiência e a colaboração em projetos de Data Science, tornando o trabalho mais acessível e compreensível para todos os envolvidos.
2.1.5 Nomes de Variáveis em R
A nomeação adequada de variáveis é crucial em programação e análise de dados, incluindo no uso de R.
Seguir boas práticas ajuda a tornar o código mais legível, compreensível. Aqui estão algumas diretrizes para a nomeação de variáveis:
2.1.6 Limitação no Número de Caracteres
Evite usar palavras de funções ou operadores (mais à frente iremos ver quais são)
Mantenha o nome da variável conciso. Embora o R permita nomes de variáveis com até 10.000 caracteres, nomes mais curtos são mais fáceis de ler e gerenciar.
2.1.6.1 Convenções de Nomeação
Evite Espaços: Os espaços não são lidos pela maioria dos sistemas de linha de comando.
Use underscore (_) ou hífen (-) como alternativas.
Evite Caracteres Especiais: Não use caracteres como ?, ., *, ,, /, +, ', &, " nos nomes das variáveis.
Em vez disso, use underscore (_) ou hífen (-), ou mude o nome para algo mais adequado.
Convenções de Nomes: As convenções mais comuns incluem:
Snake Case: data_science
Camel Case: dataScience
2.1.6.2 Unicidade e Clareza
Nomes de Variáveis Devem Ser Únicos: Cada variável deve ter um nome distinto.
Nomes Claros e Explícitos: O nome da variável deve claramente indicar o que ela representa.
2.1.6.3 Metadados e Alterações
Incluir Metadados Relevantes: Quando aplicável, inclua informações como escala, alterações, número/versão e tipo de variável no nome.
Mudança de Nome com Alterações Significativas: Altere o nome da variável apenas se houver uma mudança substancial em seu conteúdo ou significado.
2.1.6.4 Consistência
Consistência em Projetos: Use convenções de nomeação consistentes em todos os projetos para manter a interoperabilidade.
Evite Caracteres Especiais: Exceto o underscore (_). O hífen (-) pode ser usado, mas com cautela, pois pode ser confundido com subtração.
Coerência na Capitalização e Separadores: Mantenha um padrão constante para capitalização e uso de separadores em nomes de variáveis.
Vamos detalhar as boas práticas para lidar com variáveis nominais e valores em falta em projetos de análise de dados, especialmente em R.
2.1.6.5 Variáveis Nominais
Variáveis nominais são aquelas que representam categorias sem qualquer ordem intrínseca (homem mulher). Boas práticas recomendadas para trabalhar com variáveis nominais:
Identificação Distinta: Cada categoria dentro de uma variável nominal deve ter um identificador único que a distinga das outras.
Representação Significativa: A codificação da variável nominal deve refletir claramente o seu significado. Por exemplo, usar “H” para “Homem” e “M” para “Mulher”.
Padronização: Manter a mesma codificação para as variáveis nominais em todo o projeto e ao longo do tempo. Isso evita confusões e erros na análise dos dados.
Clareza na Ordenação: Quando lidar com fatores ordinais (categorias com uma ordem natural), a ordem deve ser clara e lógica, facilitando a compreensão e a análise.
2.1.7 Valores em Falta (Missing data)
Valores em falta podem ocorrer por várias razões e seu tratamento adequado é crucial para análises precisas.
Padronização de Códigos para Valores em Falta: Utilize um código padrão para representar valores em falta em todo o dataset.
Evitar Ambiguidades: O código para valores em falta deve ser inequívoco e não confundível com valores reais dos dados.
Incluir Razões para Dados missing: Pode ser útil usar códigos diferentes para indicar diferentes razões pelas quais os dados estão faltando.
Tipo Correspondente de Dados missing: Ao atribuir um valor para representar dados faltantes, certifique-se de que ele corresponda ao tipo da variável. Por exemplo, use “NA_character_” para variáveis de caracteres ou “NA_real_” para variáveis numéricas.
2.1.8 Estrutura de Código
Claro, aqui estão algumas boas práticas de escrita de código em R, focando especialmente em comentários, uso de espaços, indentação e limites de linha:
2.1.8.1 Usar Comentários
Comentários são fundamentais para explicar o que o código faz, tornando-o mais legível e compreensível tanto para você quanto para outros que possam usar ou revisar seu código no futuro.
Comentários Claros e Concisos: Escreva comentários que expliquem claramente a função do código ou as decisões tomadas. Evite comentários redundantes que apenas repetem o que o código já indica.
Documentar as Etapas do Processo: Use comentários para descrever as etapas lógicas do código, especialmente em seções mais complexas ou menos intuitivas.
Atualizar os Comentários: Certifique-se de que os comentários permaneçam atualizados conforme você modifica o código.
Código
# isto é um comentários# autoria: JDionisio# data de alterção
2.1.8.2 Usar Espaços e Identação
Espaços e indentação ajudam a tornar o código mais legível e organizado. Eles são essenciais para a legibilidade e manutenção do código.
Espaçamento Consistente: Use espaços em torno de operadores (por exemplo, x + y, não x+y) e após vírgulas (por exemplo, c(1, 2, 3)).
Indentação para Estruturas de Controle: Use indentação para blocos de código dentro de estruturas de controle, como if, for, while, e funções. Isso ajuda a visualizar a estrutura do código.
Indentação Consistente: Mantenha a consistência na quantidade de espaços usados para a indentação (usualmente dois ou quatro espaços ou um tab).
Código
# Mau código# É o código mais conciso em espaço mas é confuso e não ajuda o leitor a perceber a mensagemsum_patients_year_speciality<-inpatient_hospital_lite|>summarise(all_patients =sum(doentes_saidos, na.rm =TRUE),days_patients =sum(dias_de_internamento, na.rm =TRUE), mean_patient_days =mean(dias_de_internamento, na.rm =TRUE), sd_patient_days =sd(dias_de_internamento, na.rm =TRUE), max_patient_days =max(dias_de_internamento, na.rm =TRUE),min_patient_days =min(dias_de_internamento, na.rm =TRUE),.by =c(year, tipo_de_especialidade))
Código
# Mais ou menos# apesar de mais claro em termos de espaço a identação não ajuda a compreender o código utilizadosum_patients_year_speciality<-inpatient_hospital_lite|>summarise(all_patients =sum(doentes_saidos, na.rm =TRUE), days_patients =sum(dias_de_internamento, na.rm =TRUE), mean_patient_days =mean(dias_de_internamento, na.rm =TRUE), sd_patient_days =sd(dias_de_internamento, na.rm =TRUE), max_patient_days =max(dias_de_internamento, na.rm =TRUE), min_patient_days =min(dias_de_internamento, na.rm =TRUE), .by =c(year, tipo_de_especialidade))
Código
# O melhor# o codigo usa a mesma identação para toda a operação de summarise clarificando que a mesma é toda uma operaçãosum_patients_year_speciality<-inpatient_hospital_lite|>summarise( all_patients =sum(doentes_saidos, na.rm =TRUE), days_patients =sum(dias_de_internamento, na.rm =TRUE), mean_patient_days =mean(dias_de_internamento, na.rm =TRUE), sd_patient_days =sd(dias_de_internamento, na.rm =TRUE), max_patient_days =max(dias_de_internamento, na.rm =TRUE), min_patient_days =min(dias_de_internamento, na.rm =TRUE), .by =c(year, tipo_de_especialidade))
2.1.8.3 Usar Caminhos Relativos
Facilita a Reprodutibilidade: Utilizar caminhos relativos em vez de caminhos absolutos é crucial para a reprodutibilidade do seu projeto. Caminhos relativos são baseados na localização atual do seu arquivo de projeto R, o que torna seu código mais portátil.
Facilita o Compartilhamento do Projeto: Quando você usa caminhos relativos, outras pessoas podem trabalhar no projeto sem a necessidade de modificar os caminhos dos arquivos.
Estrutura de Pastas Consistente: Mantenha uma estrutura de pastas consistente e lógica em seu projeto para que os caminhos relativos sejam intuitivos e fáceis de seguir.
2.1.8.4 Evitar Repetição
Criar Funções ou Loops: Se um chunk de código está a ser repetido várias vezes, considere usar uma função ou usar loops. Isso reduz a repetição, e torna o código mais organizado e fácil de manter.
2.2 ESTRUTURAS DE DADOS
2.2.1 Objetos ‘scalar’ (1 dimensão)
Objetos em R são a base para armazenar e manipular dados permitindo uma maior abstração dos mesmos e uma manipulação direta por vinculação a um nome. O objecto com um valor é um scalar
Esta ligação é dinâmica, significa que as variáveis podem ser reatribuidas e rescritas sem que disso surja um erro.
No contexto da saúde, eles podem representar desde dados de pacientes até resultados de análises.
Código
# aqui criamos a variavel da paciente_idade com o valor 30paciente_idade<-30# aqui criamos a variavel da paciente_nome com o valor "Anaªpaciente_nome<-"Ana"
2.2.2 Vetores (2 dimensões)
Vetores são coleções unidimensionais de elementos. Existem dois tipos principais:
Vetores atómico (apenas um tipo de dados - como integer, double, character)
Listas (mais que um tipo de dados)
Em saúde, eles podem ser usados para armazenar uma séries de medições, como temperaturas corporais de um grupo de pacientes ou um conjunto de idades ou níveis de uma representação.
Código
# a variável temperatura tem 3 valores com os valores numéricos 36.5, 37.2,temperaturas<-c(36.5, 37.2, 38.0)
2.2.3 Dataframes e Tibbles (3 dimensoes)
Dataframes e tibbles são estruturas de dados tabulares.
Cada vetor na lista representa uma coluna.
Dataframes são extremamente flexíveis, permitindo colunas de diferentes tipos mas cada coluna é de apenas um tipo.
Eles são essenciais para o manipulação de conjuntos de dados clínicos, permitindo armazenar diferentes tipos de dados em colunas e linhas.
Código
dados_pacientes<-data.frame( Idade =c(25, 30, 45), Nome =c("João", "Ana", "Marta"), Temperatura =c(36.6, 37.5, 38.2))
Nota
O formato tabular deve garantir que cada observação linha é única.
2.2.4 Listas (4 dimensoes)
Listas em R são coleções que podem conter diferentes tipos de elementos.
São os mais diferentes de conceptualizar mas cada elemento na listas pode ter 1, 2, 3 ou 4 dimensoes
Nota
Podem existir listas de listas.
São úteis para armazenar dados múltiplos com uma estrutura complexa.
Código
paciente_info<-list(nome ="Ana", idade =30, temperatura =37.5, dados_pacientes,temperaturas)
2.3 NOTAÇÃO R
Existem dois grandes tipos de notação em R para aceder a elementos das estruturas de dados.
Notação com Sinal de Dólar $ e parênteses rectos []
A notação em Dólar tem a seguinte sintaxe:
Objeto a referenciar
Estrutura nomeada
Aviso
A estrutura mínima para o uso da notação de dólar é o dataframe. Não pode ser usada em vectores ou elementos (1 e 2 dimensões)
A notação em Parênteses Curvos [] tem a seguinte sintaxe:
Objeto a referenciar
Referir posição da estrutura a referenciar
Código
# este cócigo retira a coluna Idadeidades_paciente<-dados_pacientes$Idade# este cócigo retira a primeira linhaprimeiro_paciente<-dados_pacientes[1,]# este cócigo retira a primeira colunaprimeira_coluna<-dados_pacientes[,1]# nas listas podem ser usadas notações aninhadas# este cócigo retira o 4 elemento da lista paciente_info e a primeira linha deste elementoprimeiro_paciente_2<-paciente_info[[4]][1,]
Nota
A notação de parênteses é mais flexível, permitindo selecionar múltiplas linhas e/ou colunas, mas é a menos intuitivas.
Em geral é preferível usar a notação de dólar por ser mais explícita e menos afetada por alterações na ordem dos dados
Nota
Em módulos mais à frente iremos abordar outras opções para gestão de versões com o uso do Git.
2.4 OPERAÇÕES
R é uma linguagem projetada para análise estatística, o que se reflete na sua riqueza de operações matemáticas e na disponibilidade de operadores.
2.4.1 Operações Matemáticas e Operadores
Existem vários operadores matemáticos:
“+”
“-”
“*”
“/”
As operações matemáticas em R são geralmente vetorizadas, o que significa que operações como adição, subtração, multiplicação e divisão podem ser aplicadas diretamente a vetores ou matrizes. Por exemplo, ao adicionar dois vetores, a adição é realizada elemento a elemento.
A vectorização é um dos pontos fortes de R, permitindo um processamento de dados eficiente e expressivo.
2.4.2 Operadores Condicionais, Relacionais e Lógicos
Para além dos operadores matemáticos temos operadores condicionais, relacionais e lógicos. Operadores Condicionais:
if (se)
else
ifelse
or (ou)
and (e)
Operadores condicionais, como if e else, são utilizados para controlar o fluxo de execução de programas.
A função ifelse é um exemplo de uma construção condicional vetorizada, que é particularmente útil para substituir elementos em um vetor com base em uma condição.
Será novamente discutido na manipulação de dados (“Data Wrangling”)
Operadores Relacionais:
Usados para realizar comparações entre elementos.
“< e >”
“>= e <=”
“== (igualdade)”
“!= diferença”
“%in% (presente em)”
Nota
Função Negate() inverte o resultado
Resultado da comparação é sempre um valor lógico. TRUE (Verdadeiro) ou FALSE (Falso).
Código
2==3
[1] FALSE
Código
2!=3
[1] TRUE
2.5 FUNÇÕES
Para evitar a repetição de código que usa as mesmas operações, podemos usar funções.
Cada função em R funciona num ambitente próprio com variáveis locais e aquelas no ambiente onde foi definida.
Cada função tem inputs ou argumentos que definem variáveis internas da função.
Funções em R são usadas para executar tarefas específicas.
Por exemplo, saber se um paciente é idoso.
2.6 Função simples
Código
# aqui definimos a função idoso idoso<-function(idade){# o que definimos dentro de function são os argumentos da mesma, neste caso será idade o argumento#é boa prática nomear o nosso argumento para algo claro e explícitoif(idade>=65){print("idoso")}else{print("não é idoso")}}# tudo o que colocamos dentro das chavetas inicais será o que queremos que seja executado na função
Qual será o output esperado para idoso(35)?
Código
# qual será o output da função idoso(35)idoso(35)
[1] "não é idoso"
Qual será o output esperado para idoso(66)?
Código
idoso(66)
[1] "idoso"
Nota
Poderiamos definir um valor padrão para a função rescrevendo da seguinte forma:
Em R, semelhante a outras linguagens de programação há a possibilidade de aninhar funções.
No entanto, em R temos outra opção que são as pipelines que usam o pipe representado pelo %>% e o |> que indicam que a estratura anterior deve ser continuada a ser alteralada pelas funções em pipe.
A capacidade de construir pipelines de processamento de dados eficientes e legíveis é crucial para a análise de dados em R de forma reprodutivel.
Código
# 3 exemplos de execução de 2 funçõesdados_pacientes<-data.frame( Idade =c(25, 30, 45), Nome =c("João", "Ana", "Marta"), Temperatura =c(36.6, 37.5, 38.2))# separate functionsmaiores_30<-which(dados_pacientes$Idade>=30)maiores_30<-length(maiores_30)# nested functionmaiores_30_2<-length(which(dados_pacientes$Idade>=30))# piped functionmaiores_30_3<-which(dados_pacientes$Idade>=30)|>length()maiores_30
[1] 2
Código
maiores_30_2
[1] 2
Código
maiores_30_3
[1] 2
2.7 BIBLIOTECAS E PACOTES
Felizmente, muitas das funções de análise que iremos falar já foram criadas por alguém.
Normalmente, um conjunto de funções é englobado num denominado pacote. Exemplos de pacotes em R:
tidyr
dplyr
ggplot2
Estes pacotes estão normalmente no CRAN (Comprehensive R Archive Network) mas nós, como utilizadores temos de os instalar e carregar para o nosso projeto.
2.7.1 Instalar
Código
# para instalar um pacote podemos utilizar a função install.packages# install.packages("tidyverse")
Só preciso de instalar uma vez o meu pacote
2.7.2 Carregar
Código
# para carregar o pacote para o projeto ativo temos de usar o comando library# library(tidyverse)
Cada vez que inicio uma sessão de R Studio tenho de carregar os pacotes necessários para a análise.
Aviso
Muitas das dúvidas que temos das funções dos pacotes podem ser esclarecidas pela documentação do mesmo.
Os pacotes dispoíveis no CRAN têm uma vinheta que inclui todas as funções disponíveis do pacotes
Aviso
Quando existem funções com o mesmo nome estão carregadas uma é escondida, sendo essa a mais recente a ser carregada.
Para referenciar uma função específica de uma biblioteca devemos usar a seguinte sintaxe: 1. pacote::função()
2.8 CONCEITOS ADICIONAIS
2.8.1 Troubleshooting
Existem vários problemas que podem surgir quando programamos, mas quando algo corre mal é normal que surjam dois tipos de mensagem.
Warning - Aviso - - Significa que o R encontrou um problema mas foi possível ultrapassar, mas cujo resultado pode não ser o requesitado. - Rever para verificar se é algo que possa ser minimizado
Erro - Erro - - Significa que existe um erro na execução do código - O erro pode só por si indicar qual é o problema. Ex: Error: Incomplete expression: max(dados_pacientes$Idade Falta um parênteses.