O objetivo desse material é apresentar os procedimentos básicos para aquisição de dados do satélite OCO-2 e processamento inicial em R.
1) Acesse o endereço https://co2.jpl.nasa.gov/
2) Acesse o Browse OCO-2 Data em Level 2 Data Set OCO-2.
3) Role a página para baixo e acesse CUSTOMIZE PRODUCT ON BUILD PAGE.
4) No menu à esquerda estarão as 9 categorias para personalizar o banco de dados.
5) Em DATA TYPE selecione OCO-2 Satellite.
6) Em PRODUCTS selecione OCO-2 Full.
7) Em DATA VERSION selecione 10.
8) Em SPATIAL + TEMPORAL selecione Customize Your Spatial + Temporal Coverage.
OPTION 01 Utilize para selecionar a área para aquisição dos dados.
OPTION 02 Utilize para selecionar o período para aquisição dos dados.
9) Em DOWN SAMPLE PRODUCT selecione Yes, I want a Level 3 data product. Altere os valores das células e o passo temporal desejado.
10) Em DATA VARIABLES selecione as variáveis desejadas.
11) Abaixo são apresentadas as opções para os filtros e o tipo de arquivo, selecione CSV FILE.
12) Forneça um endereço de e-mail para onde os links serão direcionados.
13) Acesse o seu e-mail, será enviado uma mensagem com o endereço dos arquivos onde você poderá acompanhar o progresso do processamento de seus dados. Ao final dessa etapa um novo e-mail é enviado informando que os dados estão disponíveis.
14) Acesse o link enviado em seu e-mail e você será direcionado a página.
15) Role a página para baixo e selecione a opção WGET File List.
16) Salve o arquivo .txt na pasta data-raw
.
Antes de realizar a leitura, recomendamos a criação da estrutra de diretórios como apresentado abaixo:
pasta data-raw/CVS que receberá o download dos arquivos CSV;
pasta data-raw/txt que receberá os arquivos TXT após a faxina inicial;
pasta data que receberá o arquivos tratados em RDS;
# Download dos dados
# buscar o nome do arquivo contendo o termo CUSTON
%>%` <- magrittr::`%>%`
nome <- dir("data-raw/", pattern = "CUSTOM")
# ler os endereços armazenados no arquivo
enderecos<-read.table(paste0("data-raw/", nome))
n_links <- nrow(enderecos)
n_split <- length(stringr::str_split(enderecos[1,1],"/",simplify = TRUE))
nomes_arquivos_csv <- stringr::str_split_fixed(enderecos[,1],"/",n=Inf)[,n_split]
nomes_arquivos_txt<-sub(".csv",".txt",nomes_arquivos_csv)
### download dos arquivos - aproximadamente 2 GB ao todo
# for(i in 1:n_links){
# download.file(enderecos[i,1],
# paste0("data-raw/CSV",nomes_arquivos_csv[i]),
# mode="wb")
# }
Aguarde até todos os arquivos serem baixados. Verifique os arquivos na pasta data-raw/CSV. No repositório do GitHub esses arquivos não serão fornecidos por serem muito grandes.
Pronto, agora temos todos os arquivos na pasta data-raw aguardando a faxina.
Os arquivos .csv
são, de maneira geral, maiores que 120 \(MB\), portanto, vamos abrir cada arquivo individualmente, filtrar valores faltantes (NA
) para a coluna de \(CO_2\) atmosférico (xco2
), e salvar em novos arquivos txt na pasta data-raw/txt. Os valos de concentração não observados têm como marcação -999999
.
for(i in 1:n_links){
da<-read.csv(paste0("data-raw/CSV/", nomes_arquivos_csv[i]), sep=",")
da <- da %>%
filter(xco2..Moles.Mole...1.. != -999999)
write.table(da,
paste0("data/TXT/",nomes_arquivos_txt[i]),
quote = FALSE,
sep="\t",row.names = FALSE)
}
Vamos agora juntar todos os arquivos em um único denominado XCO2_20142020.rds
para posterior processamento.
# Lendo os arquivo totais
for(i in 1:n_links){
if(i == 1){
tab<-read.table(paste0("data-raw/TXT/",nomes_arquivos_txt[i]),h=TRUE,sep="\t")
}else{
da<-read.table(paste0("data-raw/TXT/",nomes_arquivos_txt[i]),h=TRUE,sep="\t")
tab<-rbind(tab,da)
}
}
dplyr::glimpse(tab)
readr::write_rds(tab,"data/XCO2_20142020.rds")
Verificar o banco de dados com a função glimpse()
do pacote dplyr
.
library(magrittr)
library(ggplot2)
library(dplyr)
library(tidyr)
source("../r/graficos.R")
source("../r/my_fun.R")
xco2 <- readr::read_rds("../data/XCO2_20142020.rds")
glimpse(xco2)
## Rows: 364,529
## Columns: 11
## $ longitude <dbl> -74.58225, -74.58225, -74.58...
## $ longitude_bnds <chr> "-74.70703125:-74.4574652778...
## $ latitude <dbl> -30.22572489, -29.97654828, ...
## $ latitude_bnds <chr> "-30.3503131952:-30.10113658...
## $ time..YYYYMMDDHHMMSS. <dbl> 2.014091e+13, 2.014091e+13, ...
## $ time_bnds..YYYYMMDDHHMMSS. <chr> "20140909000000:201409100000...
## $ altitude..km. <dbl> 3307.8, 3307.8, 3307.8, 3307...
## $ alt_bnds..km. <chr> "0.0:6615.59960938", "0.0:66...
## $ fluorescence_offset_relative_771nm_idp <dbl> 0.012406800, 0.010696600, -0...
## $ fluorescence_offset_relative_757nm_idp <dbl> -3.58630e+00, 8.81219e-02, -...
## $ xco2..Moles.Mole...1.. <dbl> 0.000394333, 0.000395080, 0....
Selecionar somente as variáveis necessárias para a sua análise, para isso, vamos criar um outro denominado oco_2
, a partir da seleção de longitude, latitude, tempo e a concentração de \(CO_2\) atmosférico:
oco_2<-xco2 %>%
select(longitude,
latitude,
time..YYYYMMDDHHMMSS.,
xco2..Moles.Mole...1..)
Agora precisamos transformar os dados de \(CO_2\) para \(ppm\), e criar uma coluna para da data, o dia mês e ano de cada observação, a partir da coluna time..YYYYMMDDHHMMSS
.
oco_2 <- oco_2 %>%
dplyr::mutate(
xco2_obs = xco2..Moles.Mole...1.. *1e06,
ano = time..YYYYMMDDHHMMSS.%/%1e10,
mês = time..YYYYMMDDHHMMSS.%/%1e8 %%100,
dia = time..YYYYMMDDHHMMSS.%/%1e6 %%100,
data = as.Date(stringr::str_c(ano,mês,dia,sep="-"))
) %>%
glimpse()
## Rows: 364,529
## Columns: 9
## $ longitude <dbl> -74.58225, -74.58225, -74.58225, -74.58225, ...
## $ latitude <dbl> -30.22572489, -29.97654828, -29.72737167, -2...
## $ time..YYYYMMDDHHMMSS. <dbl> 2.014091e+13, 2.014091e+13, 2.014091e+13, 2....
## $ xco2..Moles.Mole...1.. <dbl> 0.000394333, 0.000395080, 0.000394728, 0.000...
## $ xco2_obs <dbl> 394.333, 395.080, 394.728, 394.420, 391.963,...
## $ ano <dbl> 2014, 2014, 2014, 2014, 2014, 2014, 2014, 20...
## $ mês <dbl> 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,...
## $ dia <dbl> 9, 9, 9, 9, 9, 9, 9, 18, 18, 11, 11, 11, 11,...
## $ data <date> 2014-09-09, 2014-09-09, 2014-09-09, 2014-09...
Vamos filtrar os dados que estão dentro de uma área desejada, para isso vamos utlizar os polígonos e funções dos pacotes geobr
e sp
.
Inicialmente, devemos plotar o mapa do Brasil, e ler os polígonos dos municípios de um estado (SP por exmplo), cada estado, cada regiões e do país como um todo.
muni <- geobr::read_municipality(code_muni = "SP",showProgress = FALSE)
estados <- geobr::read_state(code_state = "all",showProgress = FALSE)
regiao <- geobr::read_region(showProgress = FALSE)
br <- geobr::read_country(showProgress = FALSE)
sp <- geobr::read_state(code_state = "SP",showProgress = FALSE)
ms <- geobr::read_state(code_state = "MS",showProgress = FALSE)
Plotando as delimitações do país.
br %>%
ggplot() +
geom_sf(fill="#2D3E50", color="#FEBF57",
size=.15, show.legend = FALSE) +
tema_mapa()
Plotando as regiões.
regiao %>%
ggplot() +
geom_sf(fill="#2D3E50", color="#FEBF57",
size=.15, show.legend = FALSE)+
tema_mapa()
Plotando as delimitações do país com os estados.
estados %>%
ggplot() +
geom_sf(fill="#2D3E50", color="#FEBF57",
size=.15, show.legend = FALSE)+
tema_mapa()
Plotando as delimitações do país com os estados específicos.
# plotar os estados
br %>%
ggplot() +
geom_sf(fill="#2D3E50", color="#FEBF57",
size=.15, show.legend = FALSE)+
geom_sf(data=sp,fill="#2D3E50", color="#FEBF57")+
geom_sf(data=ms,fill="#2D3E50", color="#FEBF57")+
tema_mapa()
Todos os munícipios de um estados.
# Fazer o plot
muni %>%
ggplot() +
geom_sf(fill="#2D3E50", color="#FEBF57",
size=.15, show.legend = FALSE)+
tema_mapa()
A partir do mapa base, vamos sobrepor os registros do objeto oco_2
.
br %>%
ggplot() +
geom_sf(fill="#2D3E50", color="#FEBF57",
size=.15, show.legend = FALSE)+
tema_mapa() +
geom_point(data=oco_2 %>% filter(ano == 2014) ,
aes(x=longitude,y=latitude),
shape=3,
col="red",
alpha=0.2)
É necessário selecionar somente aqueles pontos dentro do polígono da área. Inicialmente devemos extrair o polígono de cada shape do pacote geobr
.
pol_sp <- as.matrix(sp$geom[[1]]) # pol estado de são paulo
pol_ms <- as.matrix(ms$geom[[1]]) # pol estado de ms
pol_br <- as.matrix(br$geom[[1]]) # pol do brasil
pol_br <- pol_br[pol_br[,1]<=-34,] # CORREÇÃO do polígono
pol_br <- pol_br[!((pol_br[,1]>=-38.8 & pol_br[,1]<=-38.6) &
(pol_br[,2]>= -19 & pol_br[,2]<= -16)),]
pol_norte <- as.matrix(regiao$geom[[1]]) # pol região norte
pol_sudeste <- as.matrix(regiao$geom[[3]]) # pol região sudeste
pol_sudeste <- pol_sudeste[pol_sudeste[,1]<=-34,] # CORREÇÃO do polígono
pol_sul <- as.matrix(regiao$geom[[4]]) # pol região sul
pol_centro_oeste <- as.matrix(regiao$geom[[5]]) # pol centro oeste
pol_nordeste <- as.matrix(regiao$geom[[2]]) # pol nordeste
pol_nordeste <- pol_nordeste[pol_nordeste[,1]<=-34,]# CORREÇÃO do polígono
pol_nordeste <- pol_nordeste[!((pol_nordeste[,1]>=-38.7 & pol_nordeste[,1]<=-38.6) &
pol_nordeste[,2]<= -15),]# CORREÇÃO do polígono
Selecionamos os pontos que estão dentro do polígono do estado de São Paulo e Mato Grosso do Sul, no nosso exemplo. Utilizaremos a função point.in.polygon()
do pacote sp
.
oco_2 <- oco_2 %>%
mutate(
point_in_pol = as.logical(sp::point.in.polygon(point.x = longitude,
point.y = latitude,
pol.x = pol_sp[,1],
pol.y = pol_sp[,2])
|
sp::point.in.polygon(point.x = longitude,
point.y = latitude,
pol.x = pol_ms[,1],
pol.y = pol_ms[,2]))
)
Vamos refazer o mapa anterior com os dados dentro do polígono.
br %>%
ggplot() +
geom_sf(fill="#2D3E50", color="#FEBF57",
size=.15, show.legend = FALSE)+
tema_mapa() +
geom_point(data=oco_2 %>% filter(point_in_pol),
aes(x=longitude,y=latitude),
shape=3,
col="red",
alpha=0.2)
Selecionamos os pontos que estão dentro do Brasil.
oco_2 <- oco_2 %>%
mutate(
point_in_pol = as.logical(sp::point.in.polygon(point.x = longitude,
point.y = latitude,
pol.x = pol_br[,1],
pol.y = pol_br[,2])))
Vamos refazer o mapa anterior com os dados dentro do polígono.
br %>%
ggplot() +
geom_sf(fill="#2D3E50", color="#FEBF57",
size=.15, show.legend = FALSE)+
tema_mapa() +
geom_point(data=oco_2 %>% filter(ano==2014, point_in_pol),
aes(x=longitude,y=latitude),
shape=3,
col="red",
alpha=0.2)
Observa-se um problema na região nordeste, pontos não alocados, então vamos adicionar a esse mapa os pontos dessa região.
oco_2 <- oco_2 %>%
mutate(
point_in_pol = as.logical(sp::point.in.polygon(point.x = longitude,
point.y = latitude,
pol.x = pol_br[,1],
pol.y = pol_br[,2])
|
sp::point.in.polygon(point.x = longitude,
point.y = latitude,
pol.x = pol_nordeste[,1],
pol.y = pol_nordeste[,2]))
)
Vamos refazer o mapa anterior com os dados dentro do polígono.
br %>%
ggplot() +
geom_sf(fill="#2D3E50", color="#FEBF57",
size=.15, show.legend = FALSE)+
tema_mapa() +
geom_point(data=oco_2 %>% filter(point_in_pol),
aes(x=longitude,y=latitude),
shape=3,
col="red",
alpha=0.2)
Vamos olhar os outliers.
oco_2 %>%
filter(point_in_pol) %>%
ggplot(aes(y=xco2..Moles.Mole...1..))+
geom_boxplot(fill="orange",outlier.colour = "red")+
coord_cartesian(xlim=c(-1,1))+
theme_classic()
O padrão de coef
é 1,5 e define o comprimento dos bigodes com base no coeficiente e na distância interquartil, com todos os pontos fora dos bigodes considerados outliers.
filtrando os outliers.
oco_2 %>%
filter(point_in_pol, xco2..Moles.Mole...1.. > limites_outlier(oco_2$xco2..Moles.Mole...1..)[1] &
xco2..Moles.Mole...1.. < limites_outlier(oco_2$xco2..Moles.Mole...1..)[2]) %>%
ggplot(aes(y=xco2..Moles.Mole...1..))+
geom_boxplot(fill="orange",outlier.colour = "red")+
coord_cartesian(xlim=c(-1,1))+
theme_classic()
oco_2 %>%
mutate(ano_mes = paste0(ano,mês)) %>%
group_by(ano,mês) %>%
ggplot(aes(y=xco2_obs,x=as.factor(mês),
fill=as.factor(mês)))+
geom_violin(trim = FALSE) +
theme(legend.position = "none")+
facet_wrap(~ano,scales = "free")+
labs(x="Mês",y="XCO2 (ppm)")+
theme_bw()
Observe a emissão de \(CO_2\) ao longo do tempo para esses dados.
oco_2 %>%
filter(point_in_pol) %>%
ggplot(aes(x=data,y=xco2_obs)) +
geom_point(color="blue") +
geom_line(color="red")
Agora devemos retirar a tendência ao longo do tempo, para isso, dentro do período específico, faremos a retirada por meio de um ajuste linear:
oco_2 %>%
arrange(data) %>%
mutate(x= 1:nrow(oco_2)) %>%
ggplot(aes(x=x,y=xco2_obs)) +
geom_point(shape=21,color="black",fill="gray") +
geom_smooth(method = "lm") +
ggpubr::stat_regline_equation(aes(
label = paste(..eq.label.., ..rr.label.., sep = "*plain(\",\")~~")))
Extrair os coeficientes \(a\) e \(b\) da análise de regressão linear (\(y = a + bX\)).
d_aux<-oco_2 %>%
arrange(data) %>%
mutate(x= 1:nrow(oco_2)) %>%
filter(point_in_pol) %>%
select(x,xco2_obs)
mod <- lm(d_aux$xco2_obs~d_aux$x)
summary.lm(mod)
##
## Call:
## lm(formula = d_aux$xco2_obs ~ d_aux$x)
##
## Residuals:
## Min 1Q Median 3Q Max
## -51.611 -1.547 0.450 2.030 47.133
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 3.931e+02 1.717e-02 22898.6 <2e-16 ***
## d_aux$x 4.353e-05 8.165e-08 533.2 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 3.307 on 147890 degrees of freedom
## Multiple R-squared: 0.6578, Adjusted R-squared: 0.6578
## F-statistic: 2.843e+05 on 1 and 147890 DF, p-value: < 2.2e-16
a<-mod$coefficients[1]
b<-mod$coefficients[2]
Criando a variável xco2_est
a partir da retirada da tendência.
oco_2 <- oco_2 %>%
arrange(data) %>%
mutate(
xco2_est = a + b * as.numeric(data),
delta = xco2_est - xco2_obs,
XCO2 = (a-delta) - (mean(xco2_obs) - a)
) %>%
glimpse()
## Rows: 364,529
## Columns: 13
## $ longitude <dbl> -72.58572, -72.33615, -72.33615, -72.08659, ...
## $ latitude <dbl> 6.154060, 5.157354, 5.406530, 3.163941, 3.41...
## $ time..YYYYMMDDHHMMSS. <dbl> 2.014091e+13, 2.014091e+13, 2.014091e+13, 2....
## $ xco2..Moles.Mole...1.. <dbl> 0.000391368, 0.000389822, 0.000388482, 0.000...
## $ xco2_obs <dbl> 391.368, 389.822, 388.482, 390.302, 386.635,...
## $ ano <dbl> 2014, 2014, 2014, 2014, 2014, 2014, 2014, 20...
## $ mês <dbl> 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,...
## $ dia <dbl> 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,...
## $ data <date> 2014-09-06, 2014-09-06, 2014-09-06, 2014-09...
## $ point_in_pol <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FA...
## $ xco2_est <dbl> 393.8232, 393.8232, 393.8232, 393.8232, 393....
## $ delta <dbl> 2.45517575, 4.00117575, 5.34117575, 3.521175...
## $ XCO2 <dbl> 382.8391, 381.2931, 379.9531, 381.7731, 378....
oco_2 %>%
# filter(point_in_pol) %>%
ggplot(aes(x=data,y=XCO2)) +
geom_point(shape=21,color="black",fill="gray")
Buscando os dados de duas regiões.
# Criando o filtro
oco_2 <- oco_2 %>%
mutate(
point_in_pol_sp_ms = as.logical(sp::point.in.polygon(point.x = longitude,
point.y = latitude,
pol.x = pol_sp[,1],
pol.y = pol_sp[,2])
|
sp::point.in.polygon(point.x = longitude,
point.y = latitude,
pol.x = pol_ms[,1],
pol.y = pol_ms[,2]))
)
# Plotando os dados
ggplot(sp) +
geom_sf(fill="#2D3E50", color="#FEBF57",
size=.15, show.legend = FALSE)+
geom_sf(data=ms,fill="#2D3E50", color="#FEBF57",
size=.15, show.legend = FALSE)+
tema_mapa() +
geom_point(data=oco_2 %>% filter(point_in_pol_sp_ms),
aes(x=longitude,y=latitude,color=xco2_est))
Pronto, agora seu projeto pode continuar…