【问题标题】:Find pattern of combination by group in R在R中按组查找组合模式
【发布时间】:2016-09-22 04:53:22
【问题描述】:

我有数据框,我的目标是通过ID找到组合var1的模式,如果每个组至少有3个类别相同,我们设置“是”,然后哪个ID具有相同的组合。

ID1: I have 4 unique categories (A,B,C,D)
ID2: I have 4 unique categories (B,C,D,F)
ID3: I have 3 unique categories (A,B,C)
ID4: I have 2 unique categories (A,B)
ID5: I have 4 unique categories (C,D,F)

我们可以看到ID1,ID2至少有3个类别相同(B,C,D),ID1和ID3有(A,B,C),ID2,ID5至少有3个相同(C,D) ,F)。所以有 4 个 ID 会有“是”只有 ID4==“否”。

ID <- c(1,1,1,1,1,2,2,2,2,2,3,3,3,3,4,4,5,5,5,5,5)
var1 <- c("A","B","C","A","D","D","C","D","B","F","A","B","C","C",
      "A","B","D","D","C","C","F")
df <- data.frame(ID,var1)
    ID var1
1   1    A
2   1    B
3   1    C
4   1    A
5   1    D
6   2    D
7   2    C
8   2    D
9   2    B
10  2    F
11  3    A
12  3    B
13  3    C
14  3    C
15  4    A
16  4    B
17  5    D
18  5    D
19  5    C
20  5    C
21  5    F

我的输出将是

    ID var1 var2    var3
1   1    A  Yes 1-2
2   1    B  Yes 1-2
3   1    C  Yes 1-2
4   1    A  Yes 1-2
5   1    D  Yes 1-2
6   2    D  Yes 1-2
7   2    C  Yes 1-2
8   2    D  Yes 1-2
9   2    B  Yes 1-2
10  2    F  Yes 1-2
11  3    A  Yes 1-3
12  3    B  Yes 1-3
13  3    C  Yes 1-3
14  3    C  Yes 1-3
15  4    A   No       4
16  4    B   No       4
17  5    D  Yes     2-5
18  5    D  Yes     2-5
19  5    C  Yes     2-5
20  5    C  Yes     2-5
21  5    F  Yes     2-5

感谢您的提前。

【问题讨论】:

  • 仅供参考 ID2 没有类别“A”
  • 对不起,我搞砸了,让我再编辑一次

标签: r pattern-matching combinations


【解决方案1】:

这个问题本质上是一个基于公共成员资格的邻接表,例如Working with Bipartite/Affiliation Network Data in R。为此,我们从数据中制作一个表格(在消除重复后),然后取叉积。

dd <- unique(df)
tab <- table(dd)
dd <- crossprod(t(tab))
diag(dd) <- 0
#    ID
# ID  1 2 3 4 5
#   1 0 3 3 2 2
#   2 3 0 2 1 3
#   3 3 2 0 2 1
#   4 2 1 2 0 0
#   5 2 3 1 0 0

上表允许我们查看 ID 共享的类别数量。现在我们只需要遍历行;对于每一行,我选择值至少为 3 (matched) 的第一个 ID。

matched <- apply(dd >= 3, MAR = 1, function(x) which(x == TRUE)[1])   
#  1  2  3  4  5 
#  2  1  1 NA  2 

所以“1”匹配“2”,“2”匹配“1”,“3”匹配“1”,“4”没有匹配,“5”匹配“2”。最后通过操作此输出来获得所需的最终产品:

out <- apply(cbind(as.numeric(names(matched)), matched), MAR = 1, function(x) {
  if (any(is.na(x))) {
    data.frame(var2 = "No", var3 = x[1])
  } else {
    data.frame(var2 = "Yes", var3 = paste(sort(x), collapse = "-"))
  }
})
out <- plyr::ldply(out, .id = "ID")

merge(df, out, all.x = TRUE)
#    ID var1 var2 var3
# 1   1    A  Yes  1-2
# 2   1    B  Yes  1-2
# 3   1    C  Yes  1-2
# 4   1    A  Yes  1-2
# 5   1    D  Yes  1-2
# 6   2    D  Yes  1-2
# 7   2    C  Yes  1-2
# 8   2    D  Yes  1-2
# 9   2    B  Yes  1-2
# 10  2    F  Yes  1-2
# 11  3    A  Yes  1-3
# 12  3    B  Yes  1-3
# 13  3    C  Yes  1-3
# 14  3    C  Yes  1-3
# 15  4    A   No    4
# 16  4    B   No    4
# 17  5    D  Yes  2-5
# 18  5    D  Yes  2-5
# 19  5    C  Yes  2-5
# 20  5    C  Yes  2-5
# 21  5    F  Yes  2-5

【讨论】:

  • 感谢您的工作,这是一个小问题,当我稍微更改数据时,例如 ID1、ID2、ID3 至少有 3 个类别相同(B、C、D),它没有给我 var3 (1-2-3),所以它适用于对,而不是三倍。
  • 如果您修改了问题,您可能希望打开一个新问题,仔细说明您的逻辑。例如。如果数据为 1:(A、B、C、D); 2:(A、B、C、D); 3:(B、C、D); 4:(A,B,C),结果应该是1-2吗? 1-2-3? 1-2-4? 1-2-3-4?
  • 谢谢,我还是按照我自己的方式尝试,如果卡住了,我会从新的问题开始。
  • 我们有什么办法可以更快地编码这个匹配= 3, MAR = 1, function(x)which(x == TRUE)[1])matched2 = 3, MAR = 1, function(x) which(x == TRUE)[2]) 匹配3 = 3, MAR = 1, function(x) which(x == TRUE)[ 3]) 匹配4 = 3, MAR = 1, 函数(x) 其中(x == TRUE)[4]) 匹配5= 3, MAR = 1, 函数(x) which(x == TRUE)[5]) rbind(matched,matched2,matched3,matched4,matched5)
  • 请打开一个新问题。 cmets部分的问题很难回答。
猜你喜欢
  • 1970-01-01
  • 2014-11-05
  • 1970-01-01
  • 2013-02-21
  • 2020-01-04
  • 2016-11-08
  • 2012-11-19
  • 2012-07-10
相关资源
最近更新 更多