【问题标题】:concatenate several grouping index into one将多个分组索引合并为一个
【发布时间】:2020-08-15 02:17:56
【问题描述】:

我面临一个问题,我必须将各种分组索引连接成一个。这是一个例子:

df <- data.frame(idx1 = c("1_1","1_1","1_2","1_3","1_4","1_4","1_5","1_6","1_6"),
                 idx2 = c("2_1","2_2","2_2","2_3","2_4","2_5","2_6","2_7","2_8"),
                 idx3 = c("3_1","3_1","3_2","3_3","3_3","3_5","3_6","3_7","3_8"))


  idx1 idx2 idx3
1  1_1  2_1  3_1
2  1_1  2_2  3_1
3  1_2  2_2  3_2
4  1_3  2_3  3_3
5  1_4  2_4  3_3
6  1_4  2_5  3_5
7  1_5  2_6  3_6
8  1_6  2_7  3_7
9  1_6  2_8  3_8

每个索引表示重复的行,用不同的方法检测到。我想创建一个连接三者的索引。例如,第 1 行和第 2 行用idx1 表示相同,第 2 和第 3 行用idx2 表示,因此第 1、2 和 3 行是相同的,应该具有相同的分组索引。

第 4 行和第 5 行具有相同的 idx3 分组索引,第 5 和第 6 行具有相同的 idx1,因此它们应该具有相同的分组索引,与第 1、2 和 3 行不同。

我确实设法编写了一个循环来创建连接索引:

df$I <- seq(df$idx1)
df$doublon_idx <- as.numeric(NA)
idx_cnt <- 1
for(i in 1:dim(df)[1]){
  if(is.na(df[i,"doublon_idx"])){
    df[i,"doublon_idx" ] <- idx_cnt
    idx_cnt <- idx_cnt + 1
  }
  df[df$I != i & df$idx1 == df[i,]$idx1,"doublon_idx"] <- df[i,"doublon_idx"]
  df[df$I != i & df$idx2 == df[i,]$idx2,"doublon_idx"] <- df[i,"doublon_idx"]
  df[df$I != i & df$idx3 == df[i,]$idx3,"doublon_idx"] <- df[i,"doublon_idx"]
}

(预期的)输出是:

  idx1 idx2 idx3 I doublon_idx
1  1_1  2_1  3_1 1           1
2  1_1  2_2  3_1 2           1
3  1_2  2_2  3_2 3           1
4  1_3  2_3  3_3 4           2
5  1_4  2_4  3_3 5           2
6  1_4  2_5  3_5 6           2
7  1_5  2_6  3_6 7           3
8  1_6  2_7  3_7 8           4
9  1_6  2_8  3_8 9           4

但我对此并不满意:它不是通用的,它使用循环,所以当表变大时它很慢。我确信有一种合并的方式,或者聪明的方式来做到这一点,我没有找到。你的是什么?可以推广到任意数量的分组索引吗?

欢迎dplyrdata.table (虽然我更喜欢data.table,如果你能同时做到这两个)

【问题讨论】:

    标签: r loops dplyr data.table grouping


    【解决方案1】:

    不确定这在您的实际数据集上会有多快。这是一种结合igraphdata.table的方法:

    library(data.table)
    setDT(df)[, rn := .I]
    
    #create edges and idx* are your vertices
    DT <- rbindlist(list(
      df[, .(s=idx1, e=idx2, rn)],
      df[, .(s=idx1, e=idx3, rn)],
      df[, .(s=idx2, e=idx3, rn)]))
    
    #find linked clusters
    library(igraph)
    g <- graph_from_data_frame(DT, directed=FALSE)
    cl <- clusters(g)$membership))
    
    #look up cluster for each vertex
    DT[, g := cl[s]]
    
    #look up grouping for each vertex
    df[unique(DT, by="rn"), on=.(rn), doublon_idx := g]
    

    输出例如1:

       idx1 idx2 idx3 rn doublon_idx
    1:  1_1  2_1  3_1  1           1
    2:  1_1  2_2  3_1  2           1
    3:  1_2  2_2  3_2  3           1
    4:  1_3  2_3  3_3  4           2
    5:  1_4  2_4  3_3  5           2
    6:  1_4  2_5  3_5  6           2
    7:  1_5  2_6  3_6  7           3
    8:  1_6  2_7  3_7  8           4
    9:  1_6  2_8  3_8  9           4
    

    输出例如2:

       idx1 idx2 idx3 rn doublon_idx
    1:  1_1  2_1  3_1  1           1
    2:  1_1  2_2  3_1  2           1
    3:  1_2  2_2  3_2  3           1
    4:  1_3  2_3  3_3  4           2
    5:  1_4  2_4  3_3  5           2
    6:  1_4  2_5  3_5  6           2
    7:  1_5  2_6  3_6  7           3
    8:  1_6  2_7  3_7  8           4
    9:  1_6  2_8  3_8  9           4
    

    【讨论】:

    • 您的解决方案更快,而且是正确的。与您的解决方案进行比较让我意识到我的循环解决方案实际上是错误的。你在这里帮了很多忙
    猜你喜欢
    • 1970-01-01
    • 2021-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-08
    • 1970-01-01
    • 2017-02-03
    • 2017-10-03
    相关资源
    最近更新 更多