r - 如何从变化的数据帧创建查找表?

标签 r dataframe dplyr tidyverse lookup-tables

我想根据更改的数据帧创建一个查找表。原始数据帧的每一行都表示给定地区编码的变化。该数据集涵盖了 2009 年至 2019 年的某个时间段。虽然一个地区可能会在该时间段内经历一些变化,但我想要 2009 年和 2019 年各区的编码。即第一个和最新的编码。

该数据框覆盖数百个地区。有些地区可能只经历一次变化,而另一些地区则经历多次变化。一个区可以合并或拆分为多个其他区。

理想的查找表如下所示:

<表类=“s-表”> <标题> coding_2009 coding_2019 <正文> 00QR S12000047 00QR S12000048 00RB S12000047 00RB S12000048

coding_2009是截至 2009 年的学区编码,并且 coding_2019是截至 2019 年的最新编码。

原始数据框(子集),其中每行显示一个更改,如下所示:

<表类=“s-表”> <标题> 过去 新 日期 <正文> 00QR S12000015 2009-01-01 S12000015 S12000047 2018-02-02 S12000015 S12000048 2018-02-02 00RB S12000015 2009-01-01 S12000024 S12000047 2018-02-02 S12000024 S12000048 2018-02-02

对于每一行,past是重新编码为 new 的代码截至date .

例如,区00QR变成S12000015 ,稍后拆分为 S12000047S12000048 .

我已经处理这个问题好几个星期了,尝试了不同的临时版本,但似乎没有一个能够始终如一地解决问题。请注意,该守则需要考虑到某些地区仅经历一项变更,而其他地区可能经历两次或更多变更。区域也可以拆分或合并,如示例所示。

理想的答案是 tidyverse .

对于代表,我选择了以下地区的子集。

感谢您的帮助!我们将不胜感激。

Reprex 数据: (您也可以超越并使用原始数据集 Changes.csv 。请参阅下面的链接)

# Library tibble (a part of tidyverse) is needed to copy paste reprex data
#install.packages("tibble") # if you need to install it
library(tibble)

data <- tibble::tribble(
        ~past,        ~new,        ~date,
       "00RJ", "S12000013", "2009-01-01",
       "00QR", "S12000015", "2009-01-01",
       "00RB", "S12000024", "2009-01-01",
       "13UD", "E07000015", "2009-01-01",
       "15UH", "E07000025", "2009-01-01",
       "00HC", "E06000024", "2009-01-01",
       "00KG", "E06000034", "2009-01-01",
       "19UD", "E07000049", "2009-01-01",
       "19UE", "E07000050", "2009-01-01",
       "19UG", "E07000051", "2009-01-01",
       "19UH", "E07000052", "2009-01-01",
       "19UJ", "E07000053", "2009-01-01",
  "E07000017", "E06000049", "2009-04-01",
  "E07000025", "E06000053", "2009-04-01",
  "E07000014", "E06000049", "2009-04-01",
  "E07000015", "E06000049", "2009-04-01",
  "S12000013", "S12000013", "2015-06-16",
  "S12000013", "S12000013", "2015-11-01",
  "S12000015", "S12000047", "2018-02-02",
  "S12000024", "S12000047", "2018-02-02",
  "S12000015", "S12000048", "2018-02-02",
  "S12000024", "S12000048", "2018-02-02",
  "E07000049", "E06000059", "2019-04-01",
  "E07000050", "E06000059", "2019-04-01",
  "E07000053", "E06000059", "2019-04-01",
  "E07000051", "E06000059", "2019-04-01",
  "E07000052", "E06000059", "2019-04-01"
  )

# Convert date to Date (after being copy pasted as tibble)
data$date <- as.Date(data$date)

对于任何感兴趣的人,此数据来自英国的 Code History Database 。您可以从下面的链接下载 zip 文件。它的文件名为 Changes.csv :https://geoportal.statistics.gov.uk/datasets/code-history-database-december-2019-for-the-united-kingdom 。请注意,在Changes.csv中, past名为geogcd_p , newgeogcddateoper_date .

最佳答案

您本质上是在查看扁平封装的树结构。使用 igraph 包可以轻松绘制图表:


library(igraph)
g <- dat %>% select( past,new ) %>% t %>% c %>% graph
plot( g )

graph

从现在开始,有很多方法可以解决这个问题,但归结为解决问题的深度优先宽度优先方法。

假设我们有几个小图是合理的。一堆经过一些更改的不同代码,而不是经过多次更改的精选少数代码。

这建议采用宽度优先方法,并且可以通过将数据连接到自身来解决,希望不要太多次:


## work with data.table for that extra speed.
setDT(dat)

## remove duplicate entries of same code
dat <- dat[, .(date=max(date)), by=.(past,new) ]

## these are the roots, all `past` values never present in `new`
roots <- dat[ !past %in% new ]

## likewise, the leaves are those that never appear as `past` , unless they are self referencing.
leaves <- unique( dat[ !new %in% past | new == past, !"past" ], by="new" )


dd <- copy(roots)

## sucessively add next step from the source data till we have arrived at leaves only.
while( !all( dd$new %in% leaves$new ) ) {
    dd <- unique(
        merge( dd, dat, by.x="new", by.y="past", all.x=TRUE )[ , .(date.x, past, new=coalesce(new.y,new), date.y=coalesce(date.y,date.x) ) ]
    )
}

## final cleanup
dd[ order(past), .(coding_2009=past,coding_2019=new) ]

输出:


> dd[ order(past), .(coding_2009=past,coding_2019=new) ]
    coding_2009 coding_2019
 1:        00HC   E06000024
 2:        00KG   E06000034
 3:        00QR   S12000047
 4:        00QR   S12000048
 5:        00RB   S12000047
 6:        00RB   S12000048
 7:        00RJ   S12000013
 8:        13UD   E06000049
 9:        15UH   E06000053
10:        19UD   E06000059
11:        19UE   E06000059
12:        19UG   E06000059
13:        19UH   E06000059
14:        19UJ   E06000059
15:   E07000014   E06000049
16:   E07000017   E06000049

现在我只查看了迷你数据集,所以我不知道代码将如何在野外执行,但你可以尝试一下。

从上图可以看出,每个图从根到叶最多有 3 个步骤,这意味着上面的 while 循环只需运行一次。

关于r - 如何从变化的数据帧创建查找表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66879816/

相关文章:

python - Pandas:将 JSON 列表值拆分为新列

重新分类栅格值,但输出栅格的最大值似乎不正确

r - 将 geom_hline 图例添加到现有的几何条图例

python - 为什么 python pandas 数据框四舍五入我的值(value)观?

Python:合并数据框并将所有值保留在单元格中(如果不相同)

r - 砍掉每个变量名的第一个字母

r - filter() 但保留没有值的组

r - tidy() 工作但 glance() 和 augment() 在回归模型中不起作用

r - 使用因子变量更改 ggplot 图表的背景颜色

r - 更改 ggplot2 中 strip 文本背景的高度无法按预期工作