如何在交集和并集的R矩阵中进行分类?

时间:2019-04-24 11:40:10

标签: r

让我们拥有此数据

> allt <- data.frame(day = rep(c("mon", "tue", "wed"), each =3), id = c(1:3,2:4,3:5))
> allt
  day id
1 mon  1
2 mon  2
3 mon  3
4 tue  2
5 tue  3
6 tue  4
7 wed  3
8 wed  4
9 wed  5

在最后一个数据框中,我们可以看到对于“星期一”,我们具有id [1,2,3],对于“星期二”,我们具有id [2,3,4]。因此,如果我们使这些向量相交,我们将得到[2,3],如果我们使它们并集,我们将得到[1,2,3,4]。这些向量的长度分别为2和4,比率为0.5。那就是我想要的电话号码。

因此,我正在寻找一种通用的方法,如何针对所有可能的组合在更多类别中获得该比率。

结果的格式可能类似于相关矩阵。为了清楚起见,我对2类交叉路口和并集感兴趣,因此例如,我不需要4路交叉路口(周一,周二,周三,周四)-只需2天交叉路口即可。

4 个答案:

答案 0 :(得分:8)

也许是这样吗?

days <- levels(allt$day)

f <- function(x, y) {
  xids <- allt$id[allt$day == x]
  yids <- allt$id[allt$day == y]
  length(intersect(xids, yids)) / length(union(xids, yids))
}
f <- Vectorize(f)

outer(days, days, f)

#      [,1] [,2] [,3]
# [1,]  1.0  0.5  0.2
# [2,]  0.5  1.0  0.5
# [3,]  0.2  0.5  1.0

(可选)通过管道将其传输到set_colnames(days)set_rownames(days)

答案 1 :(得分:1)

这应该可以解决问题,您还可以进行更多组合,但要更改combn函数中的值。

# Creating your dataset
monday<-data.frame(day=rep("mon",3),id=c(1:3))
tuesday<-data.frame(day=rep("tue",3),id=c(2:4))
saturday<-data.frame(day=rep("sat",3),id=c(3:5))
allt<-rbind(monday,tuesday,saturday)

# Creating a list of values pr day    
library(dplyr)
aggregated_form <- allt %>%
  group_by(day) %>%
  summarise(ids = list(id))

# Function takes a list with two vectors and make intersect/join    
intersecter <- function(list_of_lists) {
  vec1 <- unlist(list_of_lists[1])
  vec2 <- unlist(list_of_lists[2])
  my_intersect <- intersect(vec1, vec2)
  my_union <- union(vec1, vec2)
  ratio <- length(my_intersect)/length(my_union)
  return(ratio)
}

# Creates strings with all combinations
combination <- sapply(combn(aggregated_form$day,2, simplify = FALSE), paste, collapse = "-")

# Calculates you value for all combinations
values <- combn(aggregated_form$ids, 2, FUN = intersecter)

# Generates a dataframe with results
results <- data.frame(comb = combination,
                      value = values)
results
     comb value
1 mon-tue   0.5
2 mon-sat   0.2
3 tue-sat   0.5

答案 2 :(得分:1)

combn(unique(allt$day), 2, function(x) 
{length(intersect(allt[allt$day == x[1],]$id, allt[allt$day == x[2],]$id)) / length(unique(allt[allt$day == x[1] | allt$day == x[2],]$id))
}, F
)

[[1]]
[1] 0.5

[[2]]
[1] 0.2

[[3]]
[1] 0.5

编辑:创建“ day-combinations-names”,可以执行类似的操作以按照相应的比率获得比率:

lapply(combn(unique(allt$day), 2, ,F), paste, collapse = "-")

[[1]]
[1] "mon-tue"

[[2]]
[1] "mon-sat"

[[3]]
[1] "tue-sat"

答案 3 :(得分:1)

首先为相交结果创建一个矩阵:

int<-mat.or.vec(nr=length(unique(allt$day)),nc=length(unique(allt$day)))
colnames(int)<-unique(allt$day)
rownames(int)<-unique(allt$day)

联合的复制矩阵:

un<-int

计算相交和并集:

for(col in colnames(int)){
  for(row in colnames(int)){
    int[row,col]<-length(intersect(allt[allt$day==col,"id"],allt[allt$day==row,"id"]))
    un[row,col]<-length(union(allt[allt$day==col,"id"],allt[allt$day==row,"id"]))
  }
}

然后,您只需将两个矩阵相除即可。

int/un

     mon tue sat
 mon 1.0 0.5 0.2
 tue 0.5 1.0 0.5
 sat 0.2 0.5 1.0