Objetivo
Este script realiza a leitura e pré-processamento de arquivos no
formato .nc4
(NetCDF) contendo dados de concentração de
dióxido de carbono atmosférico (XCO₂) medidos pelo satélite OCO-2 da
NASA. Os dados são filtrados para a região do Brasil e estruturados em
um formato tabular para análises posteriores.
Identifica todos os arquivos com extensão .nc4 no diretório data-raw/nc4/ e retorna um vetor com os caminhos completos dos arquivos para leitura posterior.
# Lista com caminho e nomes dos arquivo a serem lidos - xco2
list_of_files <- list.files("data-raw/nc4/",
pattern = ".nc4",
full.names = TRUE)
Utilizamos o pacote {geobr}
para carregar o polígono do
território brasileiro e extrai as coordenadas do polígono e converte
para uma matriz (formato necessário para a função de filtro espacial).
Após isso definimos uma função que verifica se um ponto (longitude,
latitude) está dentro do polígono do Brasil por meio da utilização da
função point.in.polygon()
do pacote {sp}
para
a operação espacial. A função retorna retorna TRUE/FALSE
para cada coordenada.
## buscando o contorno do Brasil
br <- geobr::read_country(showProgress = FALSE)
pol_br <- br$geom |> purrr::pluck(1) |> as.matrix()
def_pol <- function(x, y, pol){
as.logical(sp::point.in.polygon(point.x = x,
point.y = y,
pol.x = pol[,1],
pol.y = pol[,2]))
}
Criação da Função principal para ler cada arquivo
.nc4
e extrair as variáveis essenciais:
+longitude, latitude: Coordenadas geográficas.
+time: Carimbo de tempo da medição.
+xco2: Concentração de CO₂ (partes por milhão - ppm).
+xco2_quality_flag e xco2_incerteza: Indicadores de qualidade e incerteza das medições.
+Fechar a conexão com o arquivo após a leitura
(nc_close()
).
## função para ler arquivos NCD4
ncdf_reader <- function(file_path){
nc_file <- ncdf4::nc_open(file_path)
df <- data.frame(
"longitude"=ncdf4::ncvar_get(nc_file,varid="longitude"),
"latitude"=ncdf4::ncvar_get(nc_file,varid="latitude"),
"time"=ncdf4::ncvar_get(nc_file,varid="time"),
"xco2"=ncdf4::ncvar_get(nc_file,varid="xco2"),
"xco2_quality_flag"=ncdf4::ncvar_get(nc_file,varid="xco2_quality_flag"),
"xco2_incerteza"=ncdf4::ncvar_get(nc_file,varid="xco2_uncertainty"),
"path" = file_path
)
ncdf4::nc_close(nc_file)
return(df)
}
O código está processando um grande volume de arquivos NetCDF
(.nc4)
contendo dados de XCO2 e filtrando apenas as
medições dentro da área geográfica de interesse do Brasil.
Como os arquivos podem ser muitos (e grandes!), o processo deve ser dividido em etapas para:
1-Evitar sobrecarregar a memória do R (lendo e processando em lotes).
2-Facilitar a depuração (se algo falhar, não se perde todo o progresso).
3-Permitir paralelização futura (cada lote poderia ser processado em núcleos diferentes).
purrr::map_df
: Aplica a função ncdf_reader
(que definimos antes) em \(1000\)
arquivos por vez e combina os resultados em um único
data.frame
e write_rds
salva o resultado em
disco no formato .rds
(eficiente para objetos do R).
Observer que se houver 10.000 arquivos, tentar ler todos de uma vez pode
travar o R por falta de memória além de que, se ocorrer um erro, não
perderemos o processamento já feito.
dff_1 <- purrr::map_df(list_of_files[1:1000],ncdf_reader)
readr::write_rds(dff_1,"data-raw/dff_1.rds")
dff_2 <- purrr::map_df(list_of_files[1001:2000],ncdf_reader)
readr::write_rds(dff_2,"data-raw/dff_2.rds")
dff_3 <- purrr::map_df(list_of_files[2001:length(list_of_files)],ncdf_reader)
readr::write_rds(dff_3,"data-raw/dff_3.rds")
df1 <- readr::read_rds("data-raw/dff_1.rds")
df1 <- df1 |>
dplyr::filter(longitude >= -80 &
longitude <= -32,
latitude >= -34 &
latitude <= 10)
dplyr::glimpse(df1)
df2 <- readr::read_rds("data-raw/dff_2.rds")
df2 <- df2 |>
dplyr::filter(longitude >= -80 &
longitude <= -32,
latitude >= -34 &
latitude <= 10)
dplyr::glimpse(df2)
df3 <- readr::read_rds("data-raw/dff_3.rds")
df3 <- df3 |>
dplyr::filter(longitude >= -80 &
longitude <= -32,
latitude >= -34 &
latitude <= 10)
dplyr::glimpse(df3)
dff <- rbind(df1,df2,df3)
dff <- dff |>
dplyr::mutate(
flag_br = def_pol(longitude, latitude, pol_br)
)
dplyr::glimpse(dff)
O processamento acima poderá ser realizado com: 1. Abordagem com purrr::map_df + Divisão Automática
library(purrr)
library(dplyr)
# Divide os arquivos em lotes de tamanho fixo (ex.: 1000 por lote)
batch_size <- 1000
file_batches <- split(list_of_files, ceiling(seq_along(list_of_files) / batch_size))
# Processa todos os lotes de uma vez e salva com nomes dinâmicos
file_batches |>
imap(~ {
df <- map_df(.x, ncdf_reader)
filter(
between(longitude, -80, -32),
between(latitude, -34, 10)
)
saveRDS(df, paste0("data-raw/dff_", .y, ".rds")) # .y = índice do lote
})
2. Abordagem com furrr (Paralelização)
library(furrr) # Versão paralela do purrr
plan(multisession, workers = 4) # Usa 4 núcleos da CPU
# Processamento paralelo
file_batches |>
future_imap(~ {
df <- future_map_df(.x, ncdf_reader) |> # Leitura paralela
filter(between(longitude, -80, -32), between(latitude, -34, 10))
saveRDS(df, paste0("data-raw/dff_", .y, ".rds"))
})
Preparando os polígonos geográficos das regiões brasileiras para análises espaciais, com um tratamento especial para ajustar os contornos.
regiao <- geobr::read_region(showProgress = FALSE)
pol_norte <- regiao$geom |> purrr::pluck(1) |> as.matrix()
pol_nordeste <- regiao$geom |> purrr::pluck(2) |> as.matrix()
pol_sudeste <- regiao$geom |> purrr::pluck(3) |> as.matrix()
pol_sul <- regiao$geom |> purrr::pluck(4) |> as.matrix()
pol_centroeste<- regiao$geom |> purrr::pluck(5) |> as.matrix()
# Retirando alguns pontos
pol_br <- pol_br[pol_br[,1]<=-34,]
pol_br <- pol_br[!((pol_br[,1]>=-38.8 & pol_br[,1]<=-38.6) &
(pol_br[,2]>= -19 & pol_br[,2]<= -16)),]
pol_nordeste <- pol_nordeste[pol_nordeste[,1]<=-34,]
pol_nordeste <- pol_nordeste[!((pol_nordeste[,1]>=-38.7 & pol_nordeste[,1]<=-38.6) & pol_nordeste[,2]<= -15),]
# Retirando alguns pontos
pol_br <- pol_br[pol_br[,1]<=-34,]
pol_br <- pol_br[!((pol_br[,1]>=-38.8 & pol_br[,1]<=-38.6) &
(pol_br[,2]>= -19 & pol_br[,2]<= -16)),]
pol_nordeste <- pol_nordeste[pol_nordeste[,1]<=-34,]
pol_nordeste <- pol_nordeste[!((pol_nordeste[,1]>=-38.7 & pol_nordeste[,1]<=-38.6) & pol_nordeste[,2]<= -15),]
# Recriando o flag_nordeste
dff <- dff |>
dplyr::mutate(
flag_br = def_pol(longitude, latitude, pol_br),
flag_nordeste = def_pol(longitude, latitude, pol_nordeste)
)
dff <- dff |>
dplyr::filter(flag_br|flag_nordeste)
data_set <- readr::read_rds("data/nasa-xco2.rds") |>
# tibble::tibble() |>
dplyr::filter(
xco2 > 0,
xco2_quality_flag == 0) |>
dplyr::mutate(
path = stringr::str_remove(path, "data-raw/nc4/|\\.nc4"),
date = lubridate::as_date(stringr::str_sub(path,12,17)),
year = lubridate::year(date),
month = lubridate::month(date),
day = lubridate::day(date),
.after = "time"
)
dplyr::glimpse(data_set)
# # Criando a coluna para os estados.
# # carregando os poligonos e funções
#
# # Leitura do banco de dados
data_set <- readr::read_rds("data/nasa-xco2.rds")
#
# # Classificando pontos
state <- 0
x <- data_set |> dplyr::pull(longitude)
y <- data_set |> dplyr::pull(latitude)
for(i in 1:nrow(data_set)) state[i] <- get_geobr_state(x[i],y[i])
data_set <- data_set |> cbind(state)
# readr::write_rds(data_set,"data/nasa-xco2.rds")
dff <- readr::read_rds("../data/nasa-xco2.rds")
br |>
ggplot2::ggplot() +
ggplot2::geom_sf(fill="white", color="#FEBF57",
size=.15, show.legend = FALSE) +
ggplot2::geom_point(data= dff |>
dplyr::sample_n(1000) |>
dplyr::filter(flag_br|flag_nordeste) ,
ggplot2::aes(x=longitude,y=latitude),
shape=3,
col="red",
alpha=0.2)