# Definir função de processamento otimizada
processa_arquivo <- function(path) {
# Configurar opção para estratos com UPA única
options(survey.lonely.psu = "adjust")
# Leitura completa do FST (já otimizado com apenas colunas necessárias)
dt <- read_fst(path, as.data.table = TRUE)
# Derivações in-place (sem cópias grandes)
dt[, `:=`(
anos_estudo = VD3005,
in_forca = VD4002 %in% c(1L, 2L),
ocupado = as.integer(VD4002 == 1L),
desocupado = as.integer(VD4002 == 2L),
tri_num = suppressWarnings(as.integer(Trimestre)),
sexo = factor(V2007, levels = c(1,2), labels = c("Homem","Mulher")),
faixa_id = faixa_idade_fast(V2009)
)]
# Limpar códigos CBO
dt[, V4010_clean := clean_cbo4(V4010)]
dt[, V4041_clean := clean_cbo4(V4041)]
# Criar variáveis que dependem dos códigos limpos
dt[, `:=`(
cbo4_emp = fifelse(VD4002 == 1L, V4010_clean, NA_character_),
ultima_ocupacao = fifelse(VD4002 == 1L, V4010_clean,
fifelse(VD4002 == 2L, V4041_clean, NA_character_))
)]
# Criar período usando tri_num já criado
dt[, periodo := sprintf("%dT%d", Ano, tri_num)]
# Grande grupo usando função existente
dt[, grande_grupo := get_cbo_grande_grupo(ultima_ocupacao)]
# Exposição IA - lookup otimizado (igual ao arquivo original)
# Garantir que V4010 seja character para o match
dt[, V4010_clean := clean_cbo4(V4010)]
# Fazer join usando merge (mais robusto que o lookup por índice)
exposicao_subset <- df_exposicao_ia[, .(cbo4, Exposure, faixa_exposicao)]
dt <- merge(dt, exposicao_subset, by.x = "V4010_clean", by.y = "cbo4", all.x = TRUE)
# Renomear colunas
setnames(dt, c("Exposure", "faixa_exposicao"), c("categoria_exp_ia", "faixa_exp_ia"))
# Garantir que ocupações não encontradas fiquem como "Sem informação" (igual ao original)
dt[is.na(faixa_exp_ia) & !is.na(V4010_clean), faixa_exp_ia := "Sem informação"]
periodo_atual <- dt$periodo[1L]
# Designs amostrais com tratamento de erro
des_per <- tryCatch({
svydesign(ids = ~UPA, strata = ~Estrato, weights = ~V1028,
data = dt[in_forca == TRUE], nest = TRUE)
}, error = function(e) {
# Se houver erro, tentar sem nest ou com opções diferentes
tryCatch({
svydesign(ids = ~UPA, strata = ~Estrato, weights = ~V1028,
data = dt[in_forca == TRUE], nest = FALSE)
}, error = function(e2) {
# Como último recurso, design sem estratificação
svydesign(ids = ~1, weights = ~V1028, data = dt[in_forca == TRUE])
})
})
des_ocupados <- tryCatch({
svydesign(ids = ~UPA, strata = ~Estrato, weights = ~V1028,
data = dt[ocupado == 1L], nest = TRUE)
}, error = function(e) {
tryCatch({
svydesign(ids = ~UPA, strata = ~Estrato, weights = ~V1028,
data = dt[ocupado == 1L], nest = FALSE)
}, error = function(e2) {
svydesign(ids = ~1, weights = ~V1028, data = dt[ocupado == 1L])
})
})
# Métricas com tratamento de erro
res_g <- svymean(~desocupado, design = des_per, na.rm = TRUE)
res_s <- svyby(~desocupado, ~sexo, design = des_per, svymean,
na.rm = TRUE, drop.empty.groups = TRUE)
res_i <- svyby(~desocupado, ~faixa_id, design = des_per, svymean,
na.rm = TRUE, drop.empty.groups = TRUE)
# Ocupação
dist_grupo <- try(
svyby(~ocupado, ~grande_grupo, design = des_ocupados, svytotal,
na.rm = TRUE, drop.empty.groups = TRUE),
silent = TRUE
)
total_ocu <- try(svytotal(~ocupado, design = des_ocupados, na.rm = TRUE), silent = TRUE)
total_ocu_num <- if (inherits(total_ocu, "try-error")) NA_real_ else as.numeric(coef(total_ocu))
# Ocupação x Sexo
dist_ocu_s <- try(
svyby(~ocupado, ~grande_grupo + sexo, design = des_ocupados, svytotal,
na.rm = TRUE, drop.empty.groups = TRUE),
silent = TRUE
)
# Exposição IA
dist_exp <- try(
svyby(~ocupado, ~faixa_exp_ia, design = des_ocupados, svytotal,
na.rm = TRUE, drop.empty.groups = TRUE),
silent = TRUE
)
# Prêmio salarial
dt_premio <- dt[!is.na(VD4016) & VD4016 > 0 & !is.na(anos_estudo) & !is.na(V1028)]
out_m1 <- out_m2 <- out_m3 <- NULL
if (nrow(dt_premio) > 100) {
# Model 1
model1 <- try(lm(log(VD4016) ~ anos_estudo, data = dt_premio), silent = TRUE)
if (!inherits(model1, "try-error")) {
s <- summary(model1)$coefficients["anos_estudo", ]
out_m1 <- data.table(periodo = periodo_atual, modelo = "Model1_sem_pesos",
coeficiente = s[["Estimate"]], erro_padrao = s[["Std. Error"]],
t_valor = s[["t value"]], p_valor = s[["Pr(>|t|)"]],
n_obs = nrow(dt_premio))
}
# Model 2 e 3 com tratamento de erro
desenho_premio <- tryCatch({
svydesign(ids = ~UPA, strata = ~Estrato, weights = ~V1028,
data = dt_premio, nest = TRUE)
}, error = function(e) {
tryCatch({
svydesign(ids = ~UPA, strata = ~Estrato, weights = ~V1028,
data = dt_premio, nest = FALSE)
}, error = function(e2) {
svydesign(ids = ~1, weights = ~V1028, data = dt_premio)
})
})
model2 <- try(svyglm(log(VD4016) ~ anos_estudo, design = desenho_premio), silent = TRUE)
if (!inherits(model2, "try-error")) {
s <- summary(model2)$coefficients["anos_estudo", ]
out_m2 <- data.table(periodo = periodo_atual, modelo = "Model2_com_pesos",
coeficiente = s[["Estimate"]], erro_padrao = s[["Std. Error"]],
t_valor = s[["t value"]], p_valor = s[["Pr(>|t|)"]],
n_obs = nrow(dt_premio))
}
dt3 <- dt_premio[!is.na(V2007) & !is.na(V2010) & !is.na(UF)]
if (nrow(dt3) > 100) {
desenho3 <- tryCatch({
svydesign(ids = ~UPA, strata = ~Estrato, weights = ~V1028, data = dt3, nest = TRUE)
}, error = function(e) {
tryCatch({
svydesign(ids = ~UPA, strata = ~Estrato, weights = ~V1028, data = dt3, nest = FALSE)
}, error = function(e2) {
svydesign(ids = ~1, weights = ~V1028, data = dt3)
})
})
model3 <- try(svyglm(
log(VD4016) ~ anos_estudo + V2009 + factor(V2007) + factor(V2010) + factor(UF),
design = desenho3
), silent = TRUE)
if (!inherits(model3, "try-error")) {
s <- summary(model3)$coefficients["anos_estudo", ]
out_m3 <- data.table(periodo = periodo_atual, modelo = "Model3_com_controles",
coeficiente = s[["Estimate"]], erro_padrao = s[["Std. Error"]],
t_valor = s[["t value"]], p_valor = s[["Pr(>|t|)"]],
n_obs = nrow(dt3))
}
}
}
list(
tabs_geral = data.table(periodo = periodo_atual,
taxa_desocupacao = 100 * as.numeric(coef(res_g)),
se = 100 * as.numeric(SE(res_g))),
tabs_sexo = data.table(periodo = periodo_atual,
sexo = as.character(res_s$sexo),
taxa = 100 * as.numeric(res_s$desocupado),
se = 100 * as.numeric(SE(res_s))),
tabs_idade = data.table(periodo = periodo_atual,
faixa_id = as.character(res_i$faixa_id),
taxa = 100 * as.numeric(res_i$desocupado),
se = 100 * as.numeric(SE(res_i))),
tabs_ocupacao_abs = if (!inherits(dist_grupo, "try-error") && !is.null(dist_grupo))
data.table(periodo = periodo_atual,
grande_grupo = as.character(dist_grupo$grande_grupo),
n_ocupados = as.numeric(dist_grupo$ocupado),
se_ocupados = as.numeric(SE(dist_grupo)),
pct_total = 100 * as.numeric(dist_grupo$ocupado) / total_ocu_num) else NULL,
tabs_ocupacao_sexo = if (!inherits(dist_ocu_s, "try-error") && !is.null(dist_ocu_s))
data.table(periodo = periodo_atual,
grande_grupo = as.character(dist_ocu_s$grande_grupo),
sexo = as.character(dist_ocu_s$sexo),
n_ocupados = as.numeric(dist_ocu_s$ocupado),
se_ocupados = as.numeric(SE(dist_ocu_s))) else NULL,
tabs_exposicao_ia = if (!inherits(dist_exp, "try-error") && !is.null(dist_exp))
data.table(periodo = periodo_atual,
faixa_exposicao = as.character(dist_exp$faixa_exp_ia),
n_ocupados = as.numeric(dist_exp$ocupado),
se_ocupados = as.numeric(SE(dist_exp)),
pct_total = if (is.finite(total_ocu_num)) 100 * as.numeric(dist_exp$ocupado) / total_ocu_num else NA_real_) else NULL,
m1 = out_m1, m2 = out_m2, m3 = out_m3
)
}
cat("✅ Função de processamento definida\n")