dplyr分组筛选优化:优先保留现任者+最高得票候选人
问题:分组筛选候选人时优先保留现任者
现有R语言dplyr代码,按城市(nm_municipio)和州(sg_uf)分组后,从candidates2024数据框中筛选每组得票最高的2位候选人:
candidates2024 <- candidates2024 %>% group_by(nm_municipio, sg_uf) %>% # 按城市和州分组 slice_max(order_by = qt_votos_nom_validos, n = 2) %>% # 选取每组得票前2的候选人 ungroup()
需加入incumbent变量的逻辑:该虚拟变量为1时表示候选人是上届当选者,为0则不是。具体规则:
- 若分组内存在现任者,需让其自动占据一个名额,另一个名额分配给剩余候选人中得票最高者;
- 若分组内无现任者,则按原逻辑执行。
当前代码会剔除得票第三但为现任者的Tiago Dias,期望保留他和得票最高的Valdice。
数据的dput如下:
structure(list(sg_uf = c("BA", "BA", "BA", "BA", "BA", "BA"), nm_municipio = c("JACARACI", "JACARACI", "JACOBINA", "JACOBINA", "JACOBINA", "JACOBINA"), cd_cargo = c(11L, 11L, 11L, 11L, 11L, 11L), ds_cargo = c("Prefeito", "Prefeito", "Prefeito", "Prefeito", "Prefeito", "Prefeito"), nr_candidato = c(40L, 55L, 35L, 40L, 65L, 50L), nm_candidato = c("DEUSDEDIT CARVALHO ROCHA", "HANNEY LADEIA SOARES FLORES", "VALDICE CASTRO VIEIRA DA SILVA", "MARIANA MATOS DE OLIVEIRA", "TIAGO MANOEL DIAS FERREIRA", "VALESSIO SOARES DE BRITO"), nm_urna_candidato = c("DETINHO", "HANNEY LADEIA", "VALDICE", "MARIANA OLIVEIRA", "TIAGO DIAS", "VALESSIO FILHO DE JACOBINA"), sg_partido = c("PSB", "PSD", "PMB", "PSB", "PC do B", "PSOL"), ds_composicao_coligacao = c("Federação BRASIL DA ESPERANÇA - FE BRASIL(PT/PC do B/PV) / AGIR / PSB", "PP / PSD", "REPUBLICANOS / PP / PDT / PL / PRD / DC / PMB / SOLIDARIEDADE", "AVANTE / Federação PSDB CIDADANIA(PSDB/CIDADANIA) / PSB", "PRTB / PSD / MOBILIZA / MDB / AGIR / PODE / Federação BRASIL DA ESPERANÇA - FE BRASIL(PT/PC do B/PV)", "Federação PSOL REDE(PSOL/REDE)"), nr_turno = c(1L, 1L, 1L, 1L, 1L, 1L), ds_sit_totalizacao = c("Eleito", "Não Eleito", "Eleito", "Não Eleito", "Não Eleito", "Não Eleito"), dt_ult_totalizacao = c("2024-10-06 20:25:25", "2024-10-06 20:25:25", "2024-10-06 20:08:52", "2024-10-06 20:08:52", "2024-10-06 20:08:52", "2024-10-06 20:08:52"), sg_ue = c(36498L, 36498L, 36510L, 36510L, 36510L, 36510L), sq_candidato = c(50002150514, 50002002442, 50002347768, 50002074476, 50002074352, 50002074411 ), nm_tipo_destinacao_votos = c("Válido", "Válido", "Válido", "Válido", "Válido", "Válido"), sq_eleicao_divulga = c(2045202024L, 2045202024L, 2045202024L, 2045202024L, 2045202024L, 2045202024L ), aa_eleicao = c(2024L, 2024L, 2024L, 2024L, 2024L, 2024L ), nm_regiao = c("NORDESTE", "NORDESTE", "NORDESTE", "NORDESTE", "NORDESTE", "NORDESTE"), pc_votos_validos = c(0.5092, 0.4908, 0.4686, 0.3296, 0.1921, 0.0097), qt_votos_nom_validos = c(4804L, 4630L, 21952L, 15444L, 9000L, 454L), qt_votos_concorrentes = c(9434L, 9434L, 46850L, 46850L, 46850L, 46850L), incumbent = c(0, 0, 0, 0, 1, 0), ranLastElection = c(0, 0, 0, 1, 1, 0)), row.names = 1088:1093, class = "data.frame")
解决方案
使用dplyr的分组逻辑结合条件筛选实现需求:
candidates2024 <- candidates2024 %>% group_by(nm_municipio, sg_uf) %>% # 分两部分筛选后合并:现任者 + 非现任得票最高者 bind_rows( # 筛选所有现任者 filter(., incumbent == 1), # 筛选非现任者,取(2 - 现任者数量)位得票最高的 filter(., incumbent == 0) %>% slice_max(order_by = qt_votos_nom_validos, n = max(0, 2 - sum(incumbent == 1))) ) %>% ungroup()
逻辑说明
- 分组后,首先提取所有
incumbent=1的候选人,确保他们被保留; - 计算每组需要从非现任者中选取的人数:
2 - 现任者数量,如果没有现任者则取2位,有1位现任则取1位; - 从非现任者中按得票降序选取对应数量的候选人;
- 将两部分结果合并,最后取消分组。
测试该代码后,JACOBINA分组会保留Valdice(得票最高的非现任)和Tiago Dias(现任者),符合需求。
内容的提问来源于stack exchange,提问作者justsomeslav
相关产品推荐
相关产品推荐

