【问题标题】:Categorizing types of duplicates in R在 R 中对重复的类型进行分类
【发布时间】:2020-02-03 04:54:57
【问题描述】:

假设我有以下数据框:

df <- data.frame(address=c('654 Peachtree St','890 River Rd','890 River Rd','890 River Rd','1234 Main St','1234 Main St','567 1st Ave','567 1st Ave'), city=c('Atlanta','Eugene','Eugene','Eugene','Portland','Portland','Pittsburgh','Etna'), state=c('GA','OR','OR','OR','OR','OR','PA','PA'), zip5=c('30308','97404','97404','97404','97201','97201','15223','15223'), zip9=c('30308-1929','97404-3253','97404-3253','97404-3253','97201-5717','97201-5000','15223-2105','15223-2105'), stringsAsFactors = FALSE)
`address              city    state zip5  zip9
1 654 Peachtree St    Atlanta    GA 30308 30308-1929
2    8910 River Rd     Eugene    OR 97404 97404-3253
3    8910 River Rd     Eugene    OR 97404 97404-3253
4    8910 River Rd     Eugene    OR 97404 97404-3253
5     1234 Main St   Portland    OR 97201 97201-5717
6     1234 Main St   Portland    OR 97201 97201-5000
7      567 1st Ave Pittsburgh    PA 15223 15223-2105
8      567 1st Ave       Etna    PA 15223 15223-2105`

我正在考虑将任何具有匹配地址和 zip5 的行重复。

在 R 中基于这两列过滤或保留重复项非常简单。我要做的是为每组重复项创建一个带有条件标签的新列,最终得到类似于以下内容:

`address        city    state    zip5  zip9      type 
1 8910 River Rd Eugene     OR    97404 97404-3253 Exact Match 
2 8910 River Rd Eugene     OR    97404 97404-3253 Exact Match 
3 8910 River Rd Eugene     OR    97404 97404-3253 Exact Match 
4  1234 Main St Portland   OR    97201 97201-5717 Different Zip9 
5  1234 Main St Portland   OR    97201 97201-5000 Different Zip9 
6  567 1st Ave  Pittsburgh PA    15223 15223-2105 Different City 
7  567 1st Ave  Etna       PA    15223 15223-2105 Different City`

(我也可以为每种重复类型设置一个 True/False 列。)

我假设解决方案将在一些 mutate+ifelse+boolean 代码中,但我认为是比较 within 每个重复的子集让我陷入困境......

有什么建议吗?

编辑: 我不相信这是 Find duplicated rows (based on 2 columns) in Data Frame in R 的副本。我可以使用该解决方案为每种重复/分组匹配类型创建一个 T/F 列,但我正在尝试创建专有类别。我的条件如何也考虑到差异?完全匹配的行应该只在“完全匹配”列上显示为真,而在所有其他列上显示为假。如果我只是通过将不同的列组合提供给group_by 来定义我的列,那么完全匹配的行将永远不会返回 False。

【问题讨论】:

  • 我不同意重复。正如编辑所说,这里的重点是识别存在差异的列,而不是消除重复。
  • 是的,你是对的。编辑后,我也觉得不一样了。

标签: r dataframe dplyr duplicates conditional-statements


【解决方案1】:

必须有一种更简单的方法,因为这涉及到将数据精炼成所需输出的相当多的步骤,但在有人提供之前,您可以尝试以下方法。

library(dplyr)
library(purrr)

key_pair <- c("address", "zip5")

map(3:1, ~combn(names(df)[!names(df) %in% key_pair], .x, function(x) list(c(key_pair, x)))) %>% 
  flatten() %>%
  set_names(c("exact match", map(.[-1], ~paste0(setdiff(names(df), .x), collapse = "|")))) %>%
  map_dfc(~duplicated(df[.x]) | duplicated(df[.x], fromLast = TRUE)) %>%
  imap_dfr(~replace(.x, .x == TRUE, .y)) %>%
  transmute(type = coalesce(!!!na_if(., FALSE))) %>%
  bind_cols(df, .) %>%
  filter(!is.na(type))

       address       city state  zip5       zip9           type
1 890 River Rd     Eugene    OR 97404 97404-3253    exact match
2 890 River Rd     Eugene    OR 97404 97404-3253    exact match
3 890 River Rd     Eugene    OR 97404 97404-3253    exact match
4 1234 Main St   Portland    OR 97201 97201-5717 different zip9
5 1234 Main St   Portland    OR 97201 97201-5000 different zip9
6  567 1st Ave Pittsburgh    PA 15223 15223-2105 different city
7  567 1st Ave       Etna    PA 15223 15223-2105 different city

【讨论】:

  • 谢谢你,它显然有效。我想我将不得不选择其他答案作为解决方案,因为它要简单得多。这样做有什么好处吗?
  • 这种方法可以处理多个差异(即,如果一个案例在州和城市上有所不同,它将返回一个结果,而不是单个差异)。它还可以轻松扩展到更多领域。
【解决方案2】:

我认为关键是按“引用”变量进行分组——这里的地址是有意义的——然后你可以计算该向量中唯一项目的数量。这不是一个完美的解决方案,因为我使用case_when 将优先考虑较早的选项(即,如果有两个不同的城市归属于一个地址和两个不同的邮政编码,你只会看到有两个不同的城市——你需要如果它与其他 case_when 语句有关,则可以解决此问题)。但是,如果您不需要完美粒度的解决方案,那么在这种情况下,获取唯一项的长度是一种合理的启发式方法。

df %>% 
  group_by(address) %>% 
  mutate( 
    match_type = case_when(
      all(
        length(unique(city))  == 1,
        length(unique(state)) == 1,
        length(unique(zip5))  == 1,
        length(unique(zip9))  == 1) ~ "Exact Match",
      length(unique(city)) > 1      ~ "Different City",
      length(unique(state)) > 1     ~ "Different State",
      length(unique(zip5)) > 1      ~ "Different Zip5",
      length(unique(zip9)) > 1      ~ "Different Zip9"
    ))

否则,您将不得不进行迭代分组(地址 + 其他变量)并在您提到的布尔列中进行变异。

编辑

如果您需要更精细的解决方案,我刚刚想到的另一种方法是利用添加 id 列 (df %&gt;% rowid_to_column("ID")),然后通过带有后缀的地址将表完全连接到自身(例如 suffix = c("a","b") ),过滤掉相同的 ID 并调用 distinct(因为每个比较都存在两次),然后您可以使用 mutate 制作布尔列以进行成对比较。它的计算量可能过于密集,具体取决于数据集的大小,但如果您有合理数量的 RAM,它应该可以在几千个规模上工作。

【讨论】:

    猜你喜欢
    • 2017-10-23
    • 1970-01-01
    • 1970-01-01
    • 2018-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多