You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于日期排序从长表提取市镇编码初始与最终值(tidyverse实现)

问题描述

我正在处理法国INSEE的v_mvt_commune_2024.csv文件,该文件记录了1943年以来法国市镇的行政变更事件。我关注DATE_EFF(生效日期)、COM_AV(变更前市镇编码)和COM_AP(变更后市镇编码)变量,已通过以下代码筛选出编码发生变更的行:

data <- 
  readr::read_csv("v_mvt_commune_2024.csv") |>
  dplyr::select(DATE_EFF, COM_AV, COM_AP) |>
  dplyr::filter(COM_AV != COM_AP)

部分数据显示,部分市镇编码会经历多次变更(例如64031先变为64113,后又变回64031)。我需要生成一张映射表,其中COM_AV为初始编码,COM_AP为该编码经过所有变更后的最终值。请问如何用tidyverse高效实现这一需求?

高效实现方案

处理这类链式编码变更,最高效的思路是将变更关系建模为有向图:每个市镇编码是图的节点,每条变更记录是从COM_AV指向COM_AP的有向边,最终找到每个节点对应的终端节点(无后续变更的编码)。结合tidyverse生态,推荐使用tidygraph包处理图结构,具体步骤如下:

1. 加载依赖包

library(tidyverse)
library(tidygraph)

2. 预处理数据并构建有向图

首先按生效日期排序,确保变更顺序符合时间逻辑(最新变更优先),再将数据转为有向图结构:

# 按生效日期排序,保证变更时序正确
sorted_changes <- data |>
  arrange(DATE_EFF)

# 将变更记录转为有向图:COM_AV → COM_AP 为一条边
commune_graph <- sorted_changes |>
  as_tbl_graph(directed = TRUE)

3. 计算初始编码到最终编码的映射

通过图分析找到每个节点的终端节点(无出边的节点,即不再发生变更的编码):

final_mapping <- commune_graph |>
  activate(nodes) |>
  mutate(
    final_code = map_chr(node_is_sink(), function(is_sink) {
      # 终端节点的最终编码就是自身
      if (is_sink) {
        name
      } else {
        # 广度优先搜索找到该节点最终指向的终端节点
        node |>
          bfs(mode = "out", unreachable = FALSE) |>
          filter(node_is_sink()) |>
          pull(name) |>
          first()
      }
    })
  ) |>
  as_tibble() |>
  rename(COM_AV = name, COM_AP = final_code)

4. 补充未变更的编码(可选)

如果需要包含从未发生变更的市镇编码,可以从原始数据中提取所有唯一编码,补充到映射表中:

# 提取所有出现过的市镇编码
all_codes <- data |>
  pivot_longer(cols = c(COM_AV, COM_AP), values_to = "code") |>
  distinct(code)

# 合并映射表,未变更的编码最终值为自身
full_mapping <- all_codes |>
  left_join(final_mapping, by = c("code" = "COM_AV")) |>
  mutate(COM_AP = coalesce(COM_AP, code)) |>
  rename(COM_AV = code)

方案说明

  • 按DATE_EFF排序确保变更时序正确,避免旧变更覆盖新变更的逻辑错误。
  • 图结构能高效处理链式、循环变更(如64031→64113→64031的情况,最终终端节点为64031)。
  • 广度优先搜索(BFS)保证在大规模数据下的查询效率,比递归遍历更稳定。

内容的提问来源于stack exchange,提问作者pure_func

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 12:06:03