查找具有相同值的唯一密钥对

Finding the unique key pair with same values

我正在尝试为以下问题找到解决方案,但无法找到解决方案,请帮助我解决逻辑问题,我也可以确定方向,我可以编码但无法提出必要的逻辑。

这是问题所在:

我有这样一个数据集:

df <- data.frame(x = c(1, 1, 2, 2, 2, 2, 3, 4, 5, 1, 2,3, 4, 7, 8, 9, 4, 10, 10, 11, 12), y = c('a', 'b', 'c','d', 'e', 'f', 'a', 'a', 'e', 'k', 'l', 'm', 'n', 'b', 'e', 'e', 'b',  'x', 'y', 'z', 'z'  ))

预期的输出应该是:

  col1  col2
  1     1,4,3, 7
  2     2,5,8,9
  10    10
  11    11, 12

逻辑:将 x 列视为键,将 y 列视为值,现在如果使用不同的 value(y) 值重复键,则所有这些键都连接在一起,作为 示例:1 与 a 和 b、k 相连,但 a 也与 4,3、7 相连。现在 2 与 c d e 和 f 相连,因此 2、5、8、9 也类似地与 z 与 11 相连和 12. 为了建立最终连接,我们可以将它们连接在一起并取出第一个键作为键,其余为逗号分隔值。

我的尝试

library(data.table)
setDT(df)
setnames(df, c('x', 'y'),c('los', 'mob'))

dfLos <- df[, .(mobconcat = paste0(mob, collapse = ',')), .(los)]
dfMob <- df[, .(losconcat = paste0(los, collapse = ',')), .(mob)]

df <- merge(df, dfMob, by='mob', all.x=TRUE)
dim(df)
df <- merge(df, dfLos, by='los', all.x=TRUE)
(showing  only few rows)
   los mob losconcat mobconcat
 1:   1   a     1,3,4     a,b,k
 2:   1   b     1,7,4     a,b,k
 3:   1   k         1     a,b,k
 4:   2   c         2 c,d,e,f,l
 5:   2   d         2 c,d,e,f,l
 6:   2   e   2,5,8,9 c,d,e,f,l
 7:   2   f         2 c,d,e,f,l
 8:   2   l         2 c,d,e,f,l

现在我被困在这里,可能是这种方法是浪费,我在这里尝试的方法是用逗号分隔所有键来获取所有键,但无法理解如何进一步实现。

非常感谢。欢迎您提出任何其他方法或扩展我的方法,我对任何人都满意。

这是一个可以满足您要求的函数。它可能不是最快或最优雅的答案...

key_connect <- function(data, key, val) {
  val_by_key <- split(data[[val]], data[[key]])
  key_by_val <- split(data[[key]], data[[val]])
  f <- function(val) unique(unlist(key_by_val[val]))
  res <- data.frame(
    ## Unique keys
    key = as.integer(names(val_by_key)),
    ## Connected keys with duplicates
    key_con = I(lapply(val_by_key, f))
  )
  ul <- unlist(res[["key_con"]], use.names = FALSE)
  ends <- cumsum(lengths(res[["key_con"]]))
  ends <- c(0L, ends[-length(ends)])
  g <- function(i, end) i[match(i, ul[seq_len(end)], 0L) == 0L]
  ## Connected keys without duplicates
  res[["key_con"]] <- Map(g, i = res[["key_con"]], end = ends)
  res <- res[lengths(res[["key_con"]]) > 0L, ]
  row.names(res) <- NULL
  res
}

key_connect(df, key = "x", val = "y")
  key    key_con
1   1 1, 3, 4, 7
2   2 2, 5, 8, 9
3  10         10
4  11     11, 12

另一个不是很漂亮的解决方案,但它是基于 data.table 的。也许有帮助。

library(data.table)
library(stringr)

df = data.table(x = c(1, 1, 2, 2, 2, 2, 3, 4, 5, 1, 2,3, 4, 7, 8, 9, 4, 10, 10, 11, 12), y = c('a', 'b', 'c','d', 'e', 'f', 'a', 'a', 'e', 'k', 'l', 'm', 'n', 'b', 'e', 'e', 'b',  'x', 'y', 'z', 'z'  ))


df2 = df[, .(conc = str_c(x, collapse = ", ")), by=y]
df3 = merge(df, df2, by="y", all=TRUE)
df4 = unique(df3[, .(conc = unlist(strsplit(str_c(conc, collapse = ", "), ", "))), by=x][order(conc)], by="conc")
df_final = df4[, .(conc = str_c(conc, collapse = ", ")), by=x][order(x)]

输出:

    x       conc
1:  1 1, 3, 4, 7
2:  2 2, 5, 8, 9
3: 10         10
4: 11     11, 12