Категоризация типов дубликатов в R - PullRequest
0 голосов
/ 05 октября 2019

Допустим, у меня есть следующий фрейм данных:

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 +, но я думаю, что это сравнение в каждом дублирующем подмножестве, в котором я застрял ...

Любой совет?

Редактировать: я не считаю, что это дубликат Найти дублированные строки(на основе 2 столбцов) в кадре данных в R . Я могу использовать это решение для создания столбца T / F для каждого типа совпадения / совпадения group_by, но я пытаюсь создать эксклюзивные категории. Как мои условия также могут учитывать различия? Строки с точным соответствием должны показывать true только в столбце «точное соответствие» и false для всех остальных столбцов. Если я определяю свои столбцы просто путем подачи различных комбинаций столбцов в group_by, строки с точным соответствием никогда не вернут False.

Ответы [ 2 ]

0 голосов
/ 05 октября 2019

Должен быть более простой способ, поскольку он включает в себя немало шагов, чтобы уточнить данные в желаемом выводе, но пока кто-то не предоставит их, вы можете попробовать следующее.

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
0 голосов
/ 05 октября 2019

Я думаю, что ключ группируется по «ссылочной» переменной - здесь адрес имеет смысл - и тогда вы можете посчитать количество уникальных элементов в этом векторе. Это не идеальное решение, поскольку при использовании 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 %>% rowid_to_column("ID")), а затем полное соединение таблицы ссам по адресу с суффиксами (например, suffix = c("a","b")), отфильтровывая идентичные идентификаторы и вызывая различные (так как каждое сравнение выполняется дважды), а затем вы можете создать логические столбцы с мутированием для парных сравнений. Это может быть слишком сложным в вычислительном отношении, в зависимости от размера вашего набора данных, но он должен работать в масштабе нескольких тысяч, если у вас есть достаточный объем оперативной памяти.

...