rm(list = ls(all.names = TRUE))
# limpa todos os objetos, incluindo os ocultos
# boa política se houver objetos antigos não relevantes
# melhoria da performance
4 Módulo 3 | Manipulação de dados
4.1 Setup e limpar o ambiente
Esta parte garante que tem as configurações padrão para todos os blocos de código R.
Pode ser definido num chunk ou no YAML com o parâmetro execute.
4.1.1 Definir seed
É importante definir a seed sempre que o R precisa realizar cálculos aleatórios, para que os resultados permaneçam constantes.
Exemplo: Bootstrapping e Inferência Bayesiana; Algoritmos de Machine Learning; Legendas móveis em gráficos;
set.seed(123)
4.1.2 Instalar e carregar bibliotecas
Sempre que se inicia uma nova sessão, as bibliotecas têm de ser carregadas.
# install.packages("tidyverse", repos = "http://cran.us.r-project.org")
# install.packages("readxl", repos = "http://cran.us.r-project.org")
# install.packages("lubridate", repos = "http://cran.us.r-project.org")
# install.packages("janitor")
# install.packages("data.table", repos = "http://cran.us.r-project.org")
# install.packages("here")
# install.packages("haven")
# install.packages("rio")
library(janitor)
library(tidyverse)
library(readxl)
library(lubridate)
library(data.table)
library(here)
library(haven)
library(rio)
# Forma alternativa de instalar vários pacotes e carregá-los
# Packages
<- c("janitor",
required_packages "tidyverse",
"rio",
"here",
"haven",
"data.table",
"lubridate",
"readxl"
)
for (pkg in required_packages) {
# install packages if not already present
if (!pkg %in% rownames(installed.packages())) {
install.packages(pkg)
}
# load packages to this current session
library(pkg, character.only = TRUE)
}remove(required_packages)
remove(pkg)
4.2 IMPORTAÇÃO DE DADOS
4.2.1 Importar dados
Em cursos anteriores usávamos pacotes específicos de importação e exportação.
# Nome do novo conjunto de dados <- read_excel("caminho")
# Use um caminho genérico para garantir a reprodutibilidade
<- read_excel("datasets/atividade_internamento_hospitalar.xlsx") inpatient_hospital
Importar dados por cliques
Pode importar um dataset no RStudio Figura 4.1 através de cliques no painel “Files” é um processo intuitivo, especialmente para quem prefere uma abordagem mais visual em vez de escrever código manualmente. Os passos são os seguintes:
Passos para Importar um Dataset no RStudio Usando o Painel “Files”
Painel “Files”: No canto inferior direito do RStudio, você encontrará várias abas, incluindo “Files”, “Plots”, “Packages”, etc. Clique na aba “Files”.
Localizar o dataset: Navegue até a pasta onde o seu arquivo de dados está armazenado. Se você acabou de iniciar um projeto novo, pode ser necessário primeiro copiar ou mover o arquivo de dados para a pasta do projeto.
Importar o Arquivo de Dados:
- Clique no arquivo desejado para selecioná-lo.
- Uma vez selecionado o arquivo, clique no botão “Import” que aparece no menu do painel. Para arquivos
.csv
, por exemplo, aparecerá uma opção “Import Dataset”.
Configurar a Importação:
- O RStudio abrirá um assistente de importação. Aqui pode visualizar os dados e definir várias opções de importação, como delimitadores, se a primeira linha contém os nomes das colunas, codificação, etc.
- Ajuste essas configurações conforme necessário até que os dados sejam exibidos corretamente na pré-visualização.
Executar e Salvar o Código de Importação:
- Uma vez satisfeito com a pré-visualização, você pode clicar no botão “Import” no assistente. Isso não só importa os dados para o ambiente do RStudio, mas também gera código na consola mas não no script.
- Tem copiar e colar esse código para o script R para utilizar e fazer render.
4.2.2 Pacote RIO
O pacote “rio” flexibilixa a importação e a exportação de dados.
Este pacote lida com múltiplos formatos:
Excel
GoogleSheets (colocar URL no lugar do ficheiro)
CSV
SAS
SPSS
STATA
JSON
Lista Completa dos formatos suportados
Ver aqui https://cran.r-project.org/web/packages/rio/vignettes/rio.html
Exemplo do uso do pacote RIO num worflow de Data Science
Relembrar: a referência dos ficheiros é o working directory que por default é o local do projeto R.
<- import("datasets/covid_inc.csv")
covid_inc <- import("datasets/hypoxia.xlsx")
hypoxia
# é possível definir folhas de Excel com o argumento which
# é possível remover linhas supérfulas com o argumento skip
# é possível transformar valores em na na importação com o argumento na - Ex: na= c("na", "NA", "9","99",Missing", "", " ")
Importação avançada
Em algumas situações em que temos múltiplos ficheiros e queremos importar o mais recente podemos fazê-lo utilizando a função file.info() e list.files()
1<- file.info(list.files("datasets", full.names = TRUE)) |>
ficheiros 2rownames_to_column(var = "path")
<- ficheiros |>
ficheiro_recente 3filter(mtime == max(mtime)) |>
4pull(path)
5<- import(ficheiro_recente) importar_recente
- 1
- Retirar os ficheiros da pasta datasets e dar a informação do mesmo
- 2
- Passar os índices (caminhos dos ficheiros) para uam coluna chamada path
- 3
- Filtra o ficheiro com o máximo da coluna mtime (data de modificação)
- 4
- Retira o caminho do ficheiro para a variável ficheiro recente
- 5
- O ficheiro é importado
4.3 MANIPULAÇÃO DADOS (DATA WRANGLING)
4.3.1 Limpeza de nomes de colunas (clean_names)
Ao trabalhar com R, a nomeação clara e consistente das colunas é crucial para garantir a facilidade de leitura, compreensão e manuseio dos dados. Isso é especialmente importante quando os nomes das colunas servem como referência para legendas de figuras ou para a manipulação de dados em scripts. Abaixo, você encontrará uma versão aprimorada do texto com boas práticas para nomear colunas em R:
1. Nomes curtos e concisos: Opte por nomes breves, e descritivos, que facilitem a compreensão do conteúdo da coluna. Nomes longos podem dificultar a leitura e a escrita do código.
2. Evitar espaços: Não use espaços nos nomes das colunas. Espaços podem levar a erros de sintaxe e complicam o acesso aos dados. Utilize underlines (_
) ou camelCase para separar palavras (por exemplo, idadeMeses
).
3. Minimizar o uso de letras maiúsculas: Como o R é sensível a maiúsculas e minúsculas, prefira nomes de colunas em minúsculas para evitar confusões e erros decorrentes de inconsistências no uso de maiúsculas/minúsculas.
4. Evitar caracteres especiais: Não inclua caracteres como &
, #
, <
, >
.
5. Consistência entre colunas: Mantenha um padrão na nomeação de colunas semelhantes. Por exemplo, se estiver usando prefixos ou sufixos em nomes de colunas relacionadas a datas, aplique essa convenção de maneira consistente em todo o conjunto de dados (por exemplo, dataInicio
, dataFim
).
# Vamos inspecionar o conjunto de dados
head(inpatient_hospital)
# A tibble: 6 × 7
Período Região Instituição Localização Geográfi…¹ Tipo de Especialidad…²
<chr> <chr> <chr> <chr> <chr>
1 2015-01 Região de S… Unidade Lo… 38.014123, -7.8721227 Especialidade Cirurgi…
2 2015-01 Região de S… Centro Hos… 40.2804158, -7.4922407 Especialidade Cirurgi…
3 2015-01 Região de S… Centro Hos… 40.6362453, -8.6543716 Especialidade Cirurgi…
4 2015-01 Região de S… Instituto … 40.2162514, -8.4103814 Especialidade Cirurgi…
5 2015-01 Região de S… Unidade Lo… 40.5309916, -7.2734793 Especialidade Cirurgi…
6 2015-01 Região de S… Centro Hos… 38.5283754, -8.8818638 Especialidade Cirurgi…
# ℹ abbreviated names: ¹`Localização Geográfica`, ²`Tipo de Especialidade`
# ℹ 2 more variables: `Doentes Saídos` <dbl>, `Dias de Internamento` <dbl>
# Como saber nomes das colunas
names(inpatient_hospital) # mais genérico
[1] "Período" "Região" "Instituição"
[4] "Localização Geográfica" "Tipo de Especialidade" "Doentes Saídos"
[7] "Dias de Internamento"
# Limpar nomes
# Este comando garante que todos os nomes das variáveis estão em minúsculas e sem espaços
<- clean_names(inpatient_hospital)
inpatient_hospital
<- clean_names(covid_inc)
covid_inc_limp
colnames(inpatient_hospital) # ver nomes alterados
[1] "periodo" "regiao" "instituicao"
[4] "localizacao_geografica" "tipo_de_especialidade" "doentes_saidos"
[7] "dias_de_internamento"
4.3.2 Alterar nomes colunas (rename)
Esta função permite renomear variáveis
A Sintaxe desta função deve ser novo_nome = nome_anterior. A variável nome_anterior deve existir nos dados senão temos um erro
<- hypoxia |>
hypoxia_clean clean_names() |>
rename(
sex = female
)
Renomeámos a variável female para a mais comum sex.
4.3.3 Selecionar variaveis (Select)
Este argumento permite selecionar variáveis; temos 7 variáveis em nosso conjunto de dados. Vamos verificar se precisamos de todas elas Figura 4.2.
# 1. Nome do conjunto de dados final
# 2. Nome do conjunto de dados original
# 3. Pipe %>% ou |> (ambos funcionam)
# 4. Argumento, neste caso, é select
<- inpatient_hospital |>
inpatient_hospital_lite select(
periodo,
instituicao,
tipo_de_especialidade,
doentes_saidos,
dias_de_internamento
)
<- inpatient_hospital |>
test select(periodo, instituicao)
# Também podemos não selecionar algumas variáveis
# PASSOS:
# 1. Crie um vetor com as variáveis alvo
# 2. use o argumento lógico ! ou para excluir as variáveis alvo
<- c("regiao", "localizacao_geografica")
target
<- inpatient_hospital |>
inpatient_hospital_exclude select(
!all_of(target)
)
# a mesma versão pode ser efetuada com o operador -
<- inpatient_hospital |>
inpatient_hospital_exclude1 select(
-regiao,
-localizacao_geografica,
-dias_de_internamento
)
4.3.4 Filtrar conteúdo (Filter)
Este argumento permite filtrar valores ou strings dentro das variáveis, ver Figura 4.3.
# 1. Nome do conjunto de dados final
# 2. Nome do conjunto de dados original
# 3. pipe %>% ou | >
# 4. argumento, neste caso, é filter
# 5. use um argumento lógico <, >, <=, ==
<- inpatient_hospital_lite |>
inpatient_hospital_less_1000 filter(dias_de_internamento <= 1000)
# Vamos inspecionar o conjunto de dados
view(inpatient_hospital_less_1000)
# Podemos usar filter para strings
<- inpatient_hospital_lite |>
inpatient_hospital_surgery filter(tipo_de_especialidade == "Especialidade Cirurgica")
<- inpatient_hospital_lite |>
inpatient_hospital_medicine filter(tipo_de_especialidade == "Especialidade Médica")
# Também podemos combinar vários filtros com argumentos lógicos & (e), | (ou)
# Podemos usar filter para strings
<- inpatient_hospital_lite |>
inpatient_hospital_surgery_less_500 filter(tipo_de_especialidade=="Especialidade Cirurgica" &
<=500)
dias_de_internamento
head(inpatient_hospital_less_1000)
# A tibble: 6 × 5
periodo instituicao tipo_de_especialidade doentes_saidos dias_de_internamento
<chr> <chr> <chr> <dbl> <dbl>
1 2015-01 Hospital Sa… Especialidade Cirurg… 149 827
2 2015-02 Hospital Dr… Especialidade Cirurg… 80 304
3 2015-04 Hospital Dr… Especialidade Cirurg… 167 686
4 2016-02 Hospital Dr… Especialidade Cirurg… 80 335
5 2016-03 Hospital Dr… Especialidade Cirurg… 125 509
6 2018-01 Unidade Loc… Especialidade Cirurg… 189 926
4.3.5 Criar variável (Mutate)
O mutate() é uma função usada para transformar ou adicionar novas colunas a um conjunto de dados (data frame ou tibble), ver Figura 4.4.
# 1. Nome do conjunto de dados final
# 2. Nome do conjunto de dados original
# 3. pipe %>% ou |>
# 4. argumento, neste caso, é mutate
# 5. especifique o nome da nova variável
# 6. adicione a função
<- inpatient_hospital_lite |>
inpatient_hospital_lite mutate(
length_patient =
round((dias_de_internamento/doentes_saidos), digits = 1)
)
# Vamos inspecionar o conjunto de dados
head(inpatient_hospital_lite)
# A tibble: 6 × 6
periodo instituicao tipo_de_especialidade doentes_saidos dias_de_internamento
<chr> <chr> <chr> <dbl> <dbl>
1 2015-01 Unidade Loc… Especialidade Cirurg… 360 2026
2 2015-01 Centro Hosp… Especialidade Cirurg… 352 2626
3 2015-01 Centro Hosp… Especialidade Cirurg… 651 3958
4 2015-01 Instituto P… Especialidade Cirurg… 330 2183
5 2015-01 Unidade Loc… Especialidade Cirurg… 329 2640
6 2015-01 Centro Hosp… Especialidade Cirurg… 525 3442
# ℹ 1 more variable: length_patient <dbl>
# Também podemos criar uma nova variável com valores fixos
<- inpatient_hospital_lite |>
inpatient_hospital_lite mutate(
new_var = 2,
fonte = "transparencia_sns",
multiplicacao = dias_de_internamento*doentes_saidos
)
# Vamos inspecionar o conjunto de dados
head(inpatient_hospital_lite)
# A tibble: 6 × 9
periodo instituicao tipo_de_especialidade doentes_saidos dias_de_internamento
<chr> <chr> <chr> <dbl> <dbl>
1 2015-01 Unidade Loc… Especialidade Cirurg… 360 2026
2 2015-01 Centro Hosp… Especialidade Cirurg… 352 2626
3 2015-01 Centro Hosp… Especialidade Cirurg… 651 3958
4 2015-01 Instituto P… Especialidade Cirurg… 330 2183
5 2015-01 Unidade Loc… Especialidade Cirurg… 329 2640
6 2015-01 Centro Hosp… Especialidade Cirurg… 525 3442
# ℹ 4 more variables: length_patient <dbl>, new_var <dbl>, fonte <chr>,
# multiplicacao <dbl>
4.3.6 Medidas sumário (summarise)
Agregação de Dados: summarise() é usada para aplicar funções de agregação a colunas de um dataset, resulta num novo conjunto de dados com um resumo estatístico. As funções comuns incluem mean(), sum(), min(), max(), median(), sd() (desvio padrão), e muitas outras.
Uso com group_by(): Frequentemente, summarise() é usada em conjunto com group_by(), o que permite calcular resumos agrupados por uma ou mais variáveis. Por exemplo, calcular a média de uma variável para diferentes grupos, ver Figura 4.5.
# Criar uma variável para armazenar a soma de todos os pacientes que tiveram alta
# PASSOS
# 1. Confirme se a variável de data é válida e está definida como as.Date
# 2. ...
# Soma inicial dos pacientes que tiveram alta do hospital
<- inpatient_hospital_lite |>
sum_patients summarise(
all_patients = sum(doentes_saidos) # Soma dos pacientes que tiveram alta
)
# Verificar a presença de valores NA (ausentes) na variável 'doentes_saidos'
anyNA(inpatient_hospital_lite$doentes_saidos)
[1] TRUE
Não obtivemos um resultado válido porque há NA no conjunto de dados, precisamos especificar para ignorar os valores NA
Para isso, usamos na.rm = TRUE
Este erro é muito comum em principiantes
# Recalculando a soma dos pacientes que tiveram alta, desta vez ignorando valores NA
<- inpatient_hospital_lite |>
sum_patients summarise(
all_patients=sum(doentes_saidos, na.rm = TRUE) # Soma com na.rm = TRUE para ignorar NA
)
# Agora, vamos somar todos os dias de internamento também
<- inpatient_hospital_lite |>
sum_patients summarise(
all_patients = sum(doentes_saidos, na.rm = TRUE), # Soma total de pacientes
days_patients = sum(dias_de_internamento, na.rm = TRUE), # Soma total dos dias de internamento
mean_patient_days = mean(dias_de_internamento, na.rm = TRUE), # Média de dias de internamento
sd_patient_days = sd(dias_de_internamento, na.rm = TRUE), # Desvio padrão dos dias de internamento
max_patient_days = max(dias_de_internamento, na.rm = TRUE), # Máximo de dias de internamento
min_patient_days = min(dias_de_internamento, na.rm = TRUE) # Mínimo de dias de internamento
)
4.3.7 Agrupar
‘Group by’ (antigo)
Por vezes é necessário agregar ou criar novas variáveis agregadas por outras variáveis. Vamos repetir o exercício anterior, mas com dados agregados por ano.
# Este código extrai a data será explorado de seguida
<- inpatient_hospital_lite |>
inpatient_hospital_lite mutate(
periodo=paste0(periodo, "-01"),
periodo=as.Date(periodo, format = "%Y-%m-%d"),
year = year(periodo),
month=lubridate::month(periodo, label = FALSE),
week=week(periodo),
weekday=lubridate::wday(periodo, label=TRUE)
)
#sumarizar por ano os dados
<- inpatient_hospital_lite |>
sum_patients_year group_by(year) |>
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)
)
head(sum_patients_year)
# A tibble: 6 × 7
year all_patients days_patients mean_patient_days sd_patient_days
<int> <dbl> <dbl> <dbl> <dbl>
1 2015 5125554 40245868 36855. 35924.
2 2016 5106995 40652359 37227. 36364.
3 2017 5040977 40595823 37176. 36370.
4 2018 4948916 41034190 37577. 36612.
5 2019 4929261 40737186 37305. 36435.
6 2020 4228122 36079624 33040. 31287.
# ℹ 2 more variables: max_patient_days <dbl>, min_patient_days <dbl>
# Podemos agregar por mais que uma variável
<- inpatient_hospital_lite |>
sum_patients_year_speciality group_by(year, tipo_de_especialidade) |>
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)
|>
) ungroup()
É boa prática fazer o ungroup após terminadas as operações em que necessitamos de variáveis agrupadas
.by ou by (novo)
A operação group_by está a ser subtituída pelo argumento .by nas operações do tidyverse.
Verbos suportados do .by
mutate(.by = )
summarise(.by = )
reframe(.by = )
filter(.by = )
slice(.by = )
slice_head(by = ) and slice_tail(by = )
slice_min(by = ) and slice_max(by = )
slice_sample(by = )
O mesmo código anterior com a nova sintaxe.
<- inpatient_hospital_lite |>
sum_patients_year 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 = year
)
# Podemos agregar por mais que uma variável
<- inpatient_hospital_lite |>
sum_patients_year_speciality 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)
)
4.3.8 Cortar dados (Slice)
As operações de cortar elementos são úteis para retirar linhas específicas, particularmente em dados ordenados.
Existem várias versões:
- slice (selecionar por posição)
- slice_head ou slice_tail (selecionar por posição no ínicio ou final dos dados)
- slice_sample (remover amostra de linhas - por número [n] ou proporção [prop])
- slice_min slice (remover amostra de linhas - por número [n] ou proporção [prop])
#retirar 2a linha
<- inpatient_hospital_lite |>
linha_2 slice(2)
#retirar os dois primeiros elementos
<- inpatient_hospital_lite |>
primeiros_2slice_head(n=2)
#remover 50% das amostras
<- inpatient_hospital_lite |>
amostra_50 slice_sample(prop=0.5)
#retirar os 50% maiores registos de estadia dos pacientes
<- inpatient_hospital_lite |>
quartil1_estadia slice_max(length_patient,prop=0.5)
4.3.9 Distinct
Por vezes queremos extrair os valores únicos de uma ou mais variáveis.
Suponhamos que queremos selcionar doentes para reavaliar no nosso estudos de pacientes de hipóxia (dataset hypoxia). Só queremos 1 doente com a combinação sexo, race, AHI score e Smoking
# limpar as variáveis do dataset
<- hypoxia_clean |>
hypoxia_clean distinct(age, sex, race, ahi, smoking)
<- length(hypoxia)
original_n <- length(hypoxia_clean) final_n
Passámos de 36 doentes para 5 doentes para o follow-up.
4.3.10 Pull
O comando Pull permite retirar um vector dos dados de uma coluna.
Pode ser útil para loops em que iteramos por vários elementos de um vector. Vamos retirar os nomes dos hospitais dos nossos dados.
<- inpatient_hospital_lite |>
hospitais 1distinct(instituicao) |>
2pull(instituicao)
3head(hospitais)
- 1
- Remover os valores distintos da variavel instituição
- 2
- Retirar um vector com cada
- 3
- Apresentar os dados dos hospitais
[1] "Unidade Local de Saúde do Baixo Alentejo, EPE"
[2] "Centro Hospitalar Universitário Cova da Beira, EPE"
[3] "Centro Hospitalar do Baixo Vouga, EPE"
[4] "Instituto Português Oncologia de Coimbra, EPE"
[5] "Unidade Local de Saúde da Guarda, EPE"
[6] "Centro Hospitalar de Setúbal, EPE"
O Pull tambem pode ser usado para facilitar inline coding
<- inpatient_hospital_lite |>
hospitais_max_doentes_saidos summarise(
max_doentes_saidos=max(doentes_saidos, na.rm = TRUE)
|> pull(max_doentes_saidos) )
O número máximo de doentes saíde foi de 3.4354^{4}
4.3.11 Quartis
A função ntile() é usada para criar uma classificação ou divisão de um vetor numérico em “n” número de grupos (tile, se forem 4 grupos é um quartil) de aproximadamente o mesmo tamanho. Essa função é particularmente útil para dividir dados contínuos em categorias discretas.
# este código cria uma nova variável quartis estadia que divide as observações de cada hospital em quartis
# os dois comandos finais sao apenas para visualização
<- inpatient_hospital_lite |>
quartis_estadia mutate(
quartis_estadia= ntile(length_patient, 4),.by = instituicao) |>
filter(instituicao=="Centro Hospitalar de Setúbal, EPE") |>
select(instituicao, length_patient, quartis_estadia) |>
arrange(length_patient)
head(quartis_estadia)
# A tibble: 6 × 3
instituicao length_patient quartis_estadia
<chr> <dbl> <int>
1 Centro Hospitalar de Setúbal, EPE 5.3 1
2 Centro Hospitalar de Setúbal, EPE 5.9 1
3 Centro Hospitalar de Setúbal, EPE 5.9 1
4 Centro Hospitalar de Setúbal, EPE 5.9 1
5 Centro Hospitalar de Setúbal, EPE 6 1
6 Centro Hospitalar de Setúbal, EPE 6 1
4.4 DATAS (DATETIME OBJECTS)
Lidar com datas pode ser complicado, mas é uma competência importante de dominar.
O tipo de dados em formato de data são muitas vezes interpretados como caracteres quando são importados.
Globalmente são objetos datetime mas podem ser POSIXt, POSIXct, and/or POSIXlt classes, ver formatos na Figura 4.6.
Existem alguns pacotes relevantes para lidade com dados em formato de data, mas o mais relevante é o “lubridate”.
# Como obter o dia e o dia e hora, relevante na criação de relatórios e de diferenças de dados e o presente
Sys.Date()
[1] "2024-10-14"
Sys.time()
[1] "2024-10-14 17:40:43 BST"
# Precisamos de um truque para alterar o conjunto de dados existente nas datas
# Vamos usar paste0, que permite colar valores em uma variável
<- inpatient_hospital_lite |>
inpatient_hospital_lite mutate(
periodo=paste0(periodo, "-01")
)
# Agora precisamos definir a variável periodo como uma data
<- inpatient_hospital_lite |>
inpatient_hospital_lite mutate(
periodo=as.Date(periodo, format = "%Y-%m-%d")
)
<- inpatient_hospital_lite |>
inpatient_hospital_lite mutate(
year = year(periodo),
month=lubridate::month(periodo, label = FALSE),
week=week(periodo),
weekday=lubridate::wday(periodo, label=TRUE)
)
# Vamos inspecionar o conjunto de dados
head(inpatient_hospital_lite)
# A tibble: 6 × 13
periodo instituicao tipo_de_especialidade doentes_saidos
<date> <chr> <chr> <dbl>
1 2015-01-01 Unidade Local de Saúde do Bai… Especialidade Cirurg… 360
2 2015-01-01 Centro Hospitalar Universitár… Especialidade Cirurg… 352
3 2015-01-01 Centro Hospitalar do Baixo Vo… Especialidade Cirurg… 651
4 2015-01-01 Instituto Português Oncologia… Especialidade Cirurg… 330
5 2015-01-01 Unidade Local de Saúde da Gua… Especialidade Cirurg… 329
6 2015-01-01 Centro Hospitalar de Setúbal,… Especialidade Cirurg… 525
# ℹ 9 more variables: dias_de_internamento <dbl>, length_patient <dbl>,
# new_var <dbl>, fonte <chr>, multiplicacao <dbl>, year <int>, month <dbl>,
# week <int>, weekday <ord>
# É possível desagrupar por dia, semana, mês e ano.
Existem muitas abreviaturas relativas aos formatos de tempo. As mesmas podem ser consultadas utilizando o código ?strptime
na consola.
Podem ser utilizadas no argumento format da função as.Date() para forçar a reconhecer como variavel de data.
Existem funções úteis neste pacote como make_date() que junta várias colunas numa única em formato data.
Por vezes os programas guardam datas em formato numérico e é necessário informar o R sobre a origem, ou o valor 0 dos dados.
Excel - as.Date(date_onset, origin = “1899-12-30”)
Mac - as.Date(date_onset, origin = “1904-01-01”)
R/Outros - as.Date(date_onset, origin = “1970-01-01”)
4.5 Ordenar Dados
A função arrange permite ordenar valores dentro de uma variável.
# Ordenar os doentes por ano e especialidade, em ordem crescente do número total de pacientes
<- sum_patients_year_speciality |>
sum_patients_year_speciality arrange(all_patients)
# Visualizar o dataframe ordenado
head(sum_patients_year_speciality)
# A tibble: 6 × 8
year tipo_de_especialidade all_patients days_patients mean_patient_days
<int> <chr> <dbl> <dbl> <dbl>
1 2022 Especialidade Médica 27610 290195 6309.
2 2022 Especialidade Cirurgica 28258 188436 4283.
3 2020 Especialidade Médica 2072265 22102427 39189.
4 2020 Especialidade Cirurgica 2155857 13977197 26472.
5 2021 Especialidade Médica 2198559 23131050 40158.
6 2021 Especialidade Cirurgica 2241712 14011698 26537.
# ℹ 3 more variables: sd_patient_days <dbl>, max_patient_days <dbl>,
# min_patient_days <dbl>
# Ordenar em ordem descendente pelo número total de pacientes
# Pode também ser usado o sintaxe arrange(desc(variável))
<- sum_patients_year_speciality |>
sum_patients_year_speciality arrange(-all_patients)
4.6 INTERMIDIATE DATA WRANGLING
4.6.1 Misturar funções
<- inpatient_hospital_lite |>
sum_patients_hospital filter(
== "Especialidade Cirurgica" &
tipo_de_especialidade == "12"
month |>
) summarise(
mean_patients = mean(doentes_saidos, na.rm = TRUE),
sd_patients = sd(doentes_saidos, na.rm = TRUE),
median_patients = median(doentes_saidos, na.rm = TRUE),
iqr_patients = IQR(doentes_saidos, na.rm = TRUE),
.by = instituicao)
4.7 Variáveis lag e lead
Podemos criar variáveis que representam o atraso ou avanço em relação a outras variaveis.
# O nosso objetivo é criar uma variação mensal das nossas variáveis de resultado
# O nosso dataset está organizado por tipo_de_especialidade e instituição
# E também com resultados acumulados por ano
# Precisamos de definir a unidade de atraso (lag)
<- inpatient_hospital_lite |>
inpatient_hospital_lite mutate(
doentes_saidos_lag =
lag(doentes_saidos, n = 1, order_by = periodo),
dias_de_internamento_lag =
lag(dias_de_internamento, n = 1, order_by = periodo)
.by= c(instituicao,tipo_de_especialidade,year)
,
)
<- inpatient_hospital_lite |>
sanity select(
periodo,
instituicao,
tipo_de_especialidade,
year,
doentes_saidos,
doentes_saidos_lag )
<-inpatient_hospital_lite |>
hospitalfilter(
=="Centro Hospitalar de Setúbal, EPE",
instituicao=="Especialidade Cirurgica",
tipo_de_especialidade=="2015"
year|>
) select(
periodo,
year,
instituicao,
doentes_saidos|>
) mutate(
doentes_saidos_lag =
lag(doentes_saidos, n = 1, order_by = periodo ),
doentes_saidos_var = doentes_saidos-doentes_saidos_lag,
doentes_saidos_var1 =
ifelse(is.na(doentes_saidos_var), doentes_saidos, doentes_saidos_var)
)
USO: Criar Variáveis de Diferença no tempo.
- Exemplo: Diferença mensal das diferenças
# Calcular a diferença mensal para pacientes e dias de internamento
<- inpatient_hospital_lite |>
inpatient_hospital_lite mutate(doentes_saidos_var = doentes_saidos - doentes_saidos_lag,
dias_de_internamento_var = dias_de_internamento - dias_de_internamento_lag)
4.8 Condições if_else
Os fluxos if_else são úteis para ir definindo níveis para determinda condição. No Excel será semelhante à utilização da fórmula IF ou SE
Estrutura da Função:
if_else(condição, verdadeiro, falso, tipo de dados faltante = NULL)
condição: Uma expressão lógica que é avaliada para cada elemento do vetor.
verdadeiro: O valor a retornar se a condição for verdadeira.
falso: O valor a retornar se a condição for falsa.
tipo de dados faltante: O tipo de dado a ser retornado em caso de valores NA. Se não especificado, assume-se NULL
<- inpatient_hospital_lite |>
inpatient_hospital_lite mutate(
doentes_saidos_var =
ifelse(is.na(doentes_saidos_var), doentes_saidos, doentes_saidos_var),
dias_de_internamento_var =
ifelse(is.na(dias_de_internamento_var), dias_de_internamento, dias_de_internamento_var)
)
<- inpatient_hospital_lite |>
inpatient_hospital_lite mutate(
cat1 = ifelse(doentes_saidos >= 1000, "Muitos doentes", "Poucos doentes"),
cat2 = ifelse(cat1 == "Poucos doentes", "Pouquissímos doentes", cat1)
)
<- inpatient_hospital_lite |>
sanaty select(periodo, instituicao, tipo_de_especialidade, year, doentes_saidos, doentes_saidos_lag, doentes_saidos_var)
4.9 Case_when
Opção Tidyverse para apresentação de condições if_else
Esta veriação permite a definição de múltiplas condições de escape.
No Excel será semelhante à utilização da fórmula IFS ou SE.S
Este tipo de fluxo pode terminar numa condição final que pode ser definida com o argumento .default ou com a condição TRUE
# Por vezes, precisamos de alterar as categorias dentro de uma variável
# Podemos usar case_when para fazer isso
# Podemos ver que o Hospital de Vila Franca de Xira e o Hospital de Braga têm duas designações diferentes que precisam de ser unificadas
# Corrigir designações inconsistentes na variável 'instituicao'
<- inpatient_hospital_lite |>
inpatient_hospital_lite mutate(
instituicao1 = case_when(
=="Hospital de Vila Franca de Xira, PPP" ~ "Hospital de Vila Franca de Xira, EPE",
instituicao =="Hospital de Braga, PPP" ~ "Hospital de Braga, EPE",
instituicao
)
)
<- inpatient_hospital_lite |>
inpatient_hospital_lite mutate(
instituicao2 = recode(
instituicao,"Hospital de Vila Franca de Xira, PPP" = "Hospital de Vila Franca de Xira, EPE",
"Hospital de Braga, PPP" = "Hospital de Braga, EPE"
)
)
<- inpatient_hospital_lite |>
inpatient_hospital_lite mutate(
instituicao1 = case_when(
=="Hospital de Vila Franca de Xira, PPP" ~ "Hospital de Vila Franca de Xira, EPE",
instituicao =="Hospital de Braga, PPP" ~ "Hospital de Braga, EPE"
instituicao
),instituicao1 = ifelse(is.na(instituicao1), instituicao, instituicao1)
)
<- inpatient_hospital_lite |>
inpatient_hospital_lite1 mutate(
instituicao = case_when(
=="Hospital de Vila Franca de Xira, PPP" ~ "Hospital de Vila Franca de Xira, EPE",
instituicao =="Hospital de Braga, PPP" ~ "Hospital de Braga, EPE",
instituicao .default = instituicao
#TRUE = instituicao - tem o mesmo resultado que a expressão anterior
) )
4.10 Mutate (avançada)
# Criar variável de duração da estadia
<- inpatient_hospital_lite |>
inpatient_hospital_lite mutate(
length_stay_var = dias_de_internamento_var / doentes_saidos_var,
length_stay_var = as.numeric(length_stay_var)
|>
) drop_na(length_stay_var) |>
filter(length_stay_var!="Inf")
# Filtrar apenas duração de estadia positiva
<- inpatient_hospital_lite |>
inpatient_hospital_lite_apenas_pos filter(length_stay_var >= 0)
Agora vamos criar um data wrangling mais complexo. Se a variável contiver uma expressão, podemos usar grepl para capturá-la e criar uma nova variável.
O grepl é uma função que permite deteção de padrões de texto dentro de expressões.
Exemplo: grepl(“Universitário”, instituicao, ignore.case = TRUE) daria verdade para a expressão “Centro Hospitalar e Universitário de Coimbra, EPE”
# Os valores de length_stay_var tem valores impossiveis
# Decidi eliminar valores abaixo de zero e acima de 150 porque me pareceu razoavel
<- inpatient_hospital_lite |>
inpatient_hospital_lite mutate(
tipo_instituicao =
case_when(
grepl("Universitário", instituicao, ignore.case = TRUE) ~ "University",
grepl("Oncologia", instituicao, ignore.case = TRUE) ~ "Cancer hospital"
),tipo_instituicao =
replace_na(tipo_instituicao, "Hospital"),
length_stay_var =
ifelse(length_stay_var<=0 | length_stay_var>150, NA, length_stay_var),
doentes_saidos_var =
ifelse(doentes_saidos_var<=0 , NA, doentes_saidos_var)
)
4.11 Wide e long tables
4.11.1 Long to wide
# Agrupar dados por período e tipo de instituição
<- inpatient_hospital_lite |>
inpatient_hospital_sum summarise(
doentes_saidos_var = sum(doentes_saidos_var, na.rm = TRUE),
.by = c(periodo, tipo_instituicao)
)
# Converter uma tabela do formato longo para largo
# PASSOS
# 1. Especificar a variável de categoria
# 2. Especificar a variável numérica
# Converter 'inpatient_hospital_sum' de longo para largo
<- inpatient_hospital_sum |>
inpatient_hospital_wide pivot_wider(
names_from = tipo_instituicao, # Nome das novas colunas vem de 'tipo_instituicao'
values_from = doentes_saidos_var # Os valores dessas colunas vêm de 'doentes_saidos_var'
)
4.11.2 Wide to long
# Converter a tabela de volta para o formato longo
# PASSOS
# 1. Especificar a variável que não será alterada
# 2. Especificar o nome da variável categórica
# 3. Especificar o nome da variável numérica
# Converter 'inpatient_hospital_wide' de largo para longo
<- inpatient_hospital_wide |>
inpatient_hospital_long pivot_longer(
!periodo, # Manter 'periodo' como está
names_to = "tipo_instituicao", # O nome das novas variáveis categóricas
values_to = "doentes_saidos_var" # O nome da nova variável numérica
)
5 JUNTAR DATASETS (JOIN)
No R, os “joins” são operações que combinam dois datasets com base em uma ou mais chaves comuns (key). Essas operações são fundamentais em análises de dados, especialmente quando se trabalha com conjuntos de dados relacionados que precisam ser combinados.
Os “join” são realizados com funções do pacote tidyverse
, cada uma com características específicas:
5.1 Tipos de join
1. Inner Join
inner_join(a, b, by = "key")
- Combina linhas de
a
eb
que têm valores correspondentes na coluna especificada emby
. - Retorna apenas as linhas que têm correspondências em ambas as tabelas.
2. Left Join
left_join(a, b, by = "key")
- Retorna todas as linhas de
a
e as linhas correspondentes deb
. - Se não houver correspondência em
b
, o resultado teráNA
nas colunas deb
.
3. Right Join
right_join(a, b, by = "key")
- Funciona como um
left_join
, mas retorna todas as linhas deb
e as linhas correspondentes dea
. - Se não houver correspondência em
a
, o resultado teráNA
nas colunas dea
.
4. Full Join
full_join(a, b, by = "key")
- Combina todas as linhas de
a
eb
, com linhas correspondentes de ambos. - Se não houver correspondência, as colunas da tabela sem correspondência terão
NA
.
5. Anti Join
anti_join(a, b, by = "key")
- Retorna as linhas de
a
que não têm correspondências emb
.
5.1.1 Como Funcionam
Especificação da key: As operações de join dependem da especificação de uma ou mais chaves (
by = "key"
). Esta key são colunas nas tabelasa
eb
que você deseja usar para combinar as linhas.Combinação de Linhas: O tipo de join determina como as linhas são combinadas e quais linhas são incluídas no resultado final.
Tratamento de Valores Ausentes: Nos joins, valores ausentes (NA) são tratados como valores que não correspondem. Portanto, eles geralmente resultam em linhas com
NA
no conjunto de dados combinado.
<- inpatient_hospital_lite |>
inpatient summarise(all_patients=sum(doentes_saidos, na.rm = TRUE),
.by = c(periodo, instituicao) )
<- import("datasets/trabalhadores_por_grupo_profissional.csv",
workers delim = ";", escape_double = FALSE, trim_ws = TRUE)
<- janitor::clean_names(workers) workers
# https://data-lessons.github.io/gapminder-R/12-joins.html
# Ler dados sobre trabalhadores
<- workers |>
workers select(periodo, instituicao, total_geral) |>
mutate(
periodo=paste0(periodo, "-01"),
periodo=as.Date(periodo)
)
<- left_join(
inpatient_workers
inpatient,
workers,by= c("periodo", "instituicao")
)
<- inner_join(
inpatient_workers_inner
inpatient,
workers,by = c("periodo", "instituicao")
|> ## |>
) mutate(
inpatient_worker_ratio = round(all_patients/ total_geral, digits = 4)
)
<- anti_join(
anti_inpatient_workers
inpatient,
workers,by=c("periodo", "instituicao")
)
5.2 Join by (atualização)
Em vez de definir o by numa acção join com um vector = ” string do nome da coluna do outro dataframe” fica o argumento join_by que é mais intuitivo.
5.2.1 Codigo antigo
<- data.frame (ano = c(1, 2,3,4,5, 6),
df nome_ano = c("Pré-clinico1", "Pré-clinico2","Clínico1", "Clínico2","Clínico3", "Clínico4"))
<- import("datasets/ment_health.csv")
ment_h1
<- ment_h1 %>%
ment_h filter(sex!=3)%>%
mutate(sex = sex-1)%>%
select(-id)%>%
mutate(across(.cols = c( sex
, psyt
, glang
, job.fns = as.factor))%>%
), mutate(across(.cols = c(year
,health.fns = as.ordered)) ),
<- ment_h1 %>%
ment_hj1 inner_join(df, by=c(year= "ano"))%>%
select(year, nome_ano)
head(ment_hj1)
year nome_ano
1 1 Pré-clinico1
2 4 Clínico2
3 3 Clínico1
4 2 Pré-clinico2
5 3 Clínico1
6 5 Clínico3
5.2.2 Codigo Novo
<- ment_h1 %>%
ment_hj2 inner_join(df, join_by(year == ano))%>%
select(year, nome_ano)
head(ment_hj1)
year nome_ano
1 1 Pré-clinico1
2 4 Clínico2
3 3 Clínico1
4 2 Pré-clinico2
5 3 Clínico1
6 5 Clínico3
Pequena alteração de sintaxe mas que torna mais clara a linguagem. Para além disso permite mudanças de nome de denominaçao com o tempo.
Exemplos da utilidade:
- Mudança da designação de uma unidade/medicamento/doença ao longo do tempo
- Criação de eventos cardíacos baseado na definição de valores de frequência cardiaca
A função closest vai fazer um rolling join em que vai andar para baixo e vai procurar o mais próximo em que é verdade o age<= idade.
Isto é útil pois age <= idade vai ser verdade para ambas as condições se age for inferior que ambos os limites levando a duplicações
Outros exemplos de joins com desigualdade.
5.3 Operações de grupos/sets
Por vezes queremos confirmar se os dados esperados se encontram num dataset para validação do mesmo.
- Saber todos os hospitais estão a reportar dados para o portal da transparência
# para este exemplo vamos remover os dados dos seguitnes hospti
<- inpatient_hospital_lite |>
inpatient_hospital_lite_diff filter(instituicao!=c("Centro Hospitalar e Universitário de Coimbra, EPE"))
#Vamos ficar com apenas os dados que estao no lite e não no lite diff
::setdiff(inpatient_hospital_lite, inpatient_hospital_lite_diff) dplyr
# A tibble: 170 × 23
periodo instituicao tipo_de_especialidade doentes_saidos
<date> <chr> <chr> <dbl>
1 2015-04-01 Centro Hospitalar e Universi… Especialidade Cirurg… 11336
2 2016-11-01 Centro Hospitalar e Universi… Especialidade Cirurg… 30800
3 2017-02-01 Centro Hospitalar e Universi… Especialidade Cirurg… 5445
4 2017-08-01 Centro Hospitalar e Universi… Especialidade Cirurg… 21843
5 2017-09-01 Centro Hospitalar e Universi… Especialidade Cirurg… 24362
6 2017-12-01 Centro Hospitalar e Universi… Especialidade Cirurg… 32885
7 2018-02-01 Centro Hospitalar e Universi… Especialidade Cirurg… 5471
8 2018-06-01 Centro Hospitalar e Universi… Especialidade Cirurg… 16446
9 2019-02-01 Centro Hospitalar e Universi… Especialidade Cirurg… 5112
10 2019-09-01 Centro Hospitalar e Universi… Especialidade Cirurg… 23019
# ℹ 160 more rows
# ℹ 19 more variables: dias_de_internamento <dbl>, length_patient <dbl>,
# new_var <dbl>, fonte <chr>, multiplicacao <dbl>, year <int>, month <dbl>,
# week <int>, weekday <ord>, doentes_saidos_lag <dbl>,
# dias_de_internamento_lag <dbl>, doentes_saidos_var <dbl>,
# dias_de_internamento_var <dbl>, cat1 <chr>, cat2 <chr>, instituicao1 <chr>,
# instituicao2 <chr>, length_stay_var <dbl>, tipo_instituicao <chr>
# Ficamos apenas com os dados de Coimbra
# podemos adidionar apenas novos dados com o union
6 OUTRAS FUNÇÕES
Algumas funções são úteis em determinadas circunstâncias específicas que se colocam aqui:
1. complete: Função utilizada para completar dados em falta - Uso: Útil em dados em série temporal
2. Funções genéricas de transformação: (as.numeric, as.double, as.character, as.factor, as.Date) - Uso: tranformação entre classes de variáveis
3. across Manipulação de múltplas variáveis ao mesmo tempo - Uso: Usar a mesma função em várias colunas ao mesmo tempo - Sintaxe: summarise(dataframe, across(selection, function without parenthesis))
4. Bind rows e Bind Colums: Combinar datasets em relação a colunas iguais ou id iguais - Uso: Juntar dados
No bind rows temos de ter colunas com nomes em comum. No bind cols temos de ter o mesmo número de linhas.
7 EXPORTAR DADOS
Exemplos da expostação com outros pacotes sem o RIO.
# A função fwrite utilizada pelo rio permite guardar ficheiros csv muito grandes
fwrite(
inpatient_hospital_lite,file = here::here("output", "datasets", paste0("inpatient_hospital_lite", ".csv"))
)
# SPSS
write_sav(
inpatient_hospital_lite,path = "output/datasets/inpatient_hospital_lite.sav"
)
## gerar ficheiros com nome dinâmicos
write_sav(
inpatient_hospital_lite,path = here::here("output", "datasets", paste0("inpatient_hospital_lite_", Sys.Date(), ".sav"))
)
# STATA
write_dta(
inpatient_hospital_lite,path = here::here("output", "datasets", paste0("inpatient_hospital_lite", ".dta"))
)
7.0.1 Exportar com RIO
# exportar os dados de hypoxia para um csv
export(hypoxia,"datasets/hypoxia.csv")
#exportar tudo como um único ficheiro Excel
export(list(hypoxia,covid_inc) ,"datasets/all_data.xlsx")