按行与R最常见的排序

时间:2015-08-09 16:25:16

标签: r

寻找这个难题的聪明解决方案。我需要对下面的数据框进行排序,以便按最常见的行排序,其他行的值为1。在sorted_df中,前4行具有最常见性,后4行具有1个共同点,后两个行没有。感谢您的帮助或指导我朝着正确的方向前进。

unsorted_df <- read.table(text="c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12
1 1 1 0 0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0 1 1 1 1
0 1 1 1 0 0 0 0 0 0 0 0
0 0 0 0 0 1 1 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 1 0 1 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 1 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0", header=T, sep="") 

sorted_df <- read.table(text="c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12
1 1 1 0 0 0 1 0 0 0 0 0
0 1 1 1 0 0 0 0 0 0 0 0
0 0 0 0 0 1 1 0 0 0 0 0
0 0 0 0 0 1 1 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 1 0 1 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 1 1 1", header=T, sep="") 

感谢您的评论,让我解释一下排序的目的 - 每行代表一个人,列是真/假属性。我试图找到那些具有最重叠/共同属性的那些。为方便起见,我希望那些有很多重叠的东西位于列表的顶部。

想象一下像IsHappy,HasCar,HasPhone等cols。所以没有基线,每一行都可以没有,一个或多个。我需要找到重叠最多的行,并将它们放在顶部以方便使用。

4 个答案:

答案 0 :(得分:4)

这应该有效:

toSting() 

不同行的相似度通过其乘积(内积,数学术语)的总和来计算。排序从第一行开始,保持不变。然后,下面附加下一个相似的行,并且已替换的行存储在用于替换的行的位置。

最终结果并不明确,因为可能会发生某行与尚未排序的任何其他行没有相似性。这种情况发生在例如第2行,并解释了看似不同的结果。

答案 1 :(得分:4)

好的,我想我得到的是OP。比较每个可能的行对,并调用给定的对R1R2,如果执行sum(R1*R2),请使用该元素和产品的总和来定义所涉及的两个行的分数那双。然后根据所有对的得分的最大值给每行给出最高分。然后按行的最大分数对行进行排序。

当有关系时,这结束仍然是任意的。

这是我的解决方案可能并不理想,但它是在尝试找出OP的含义时创建的,所以请注意。

unsorted_df <- read.table(text="c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12
1 1 1 0 0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0 1 1 1 1
0 1 1 1 0 0 0 0 0 0 0 0
0 0 0 0 0 1 1 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 1 0 1 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 1 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0", header=T, sep="")



N <- nrow(unsorted_df)
same1 <- function(x,y) sum((x+y)==2, na.rm=TRUE)
df_list <- unlist(apply(unsorted_df, 1, list),F,F)
df_combos <- which(upper.tri(matrix(NA, nrow=N, ncol=N)),arr.ind=T) #expand.grid(1:length(df_list),1:length(df_list))
commonality <- mapply(same1, df_list[df_combos[,1]], df_list[df_combos[,2]])
best_match <- c()
for(i in 1:length(df_list)){
    best_match[i] <- max(commonality[apply(df_combos,1,function(x)i%in%x)])
}

unsorted_df[order(best_match, decreasing=TRUE),]

   c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12
1   1  1  1  0  0  0  1  0  0   0   0   0
3   0  1  1  1  0  0  0  0  0   0   0   0
4   0  0  0  0  0  1  1  0  0   0   0   0
9   0  0  0  0  0  1  1  0  0   0   0   0
5   0  0  0  0  0  1  0  0  0   0   0   0
6   0  0  0  0  0  1  0  0  0   0   0   0
7   0  0  0  0  0  1  0  1  0   0   0   0
8   0  0  0  0  0  1  0  0  0   0   0   0
2   0  0  0  0  0  0  0  0  1   1   1   1
10  0  0  0  0  0  0  0  0  0   0   0   0

答案 2 :(得分:2)

再次参加聚会,但我相信保留你努力工作的数据 例如:为什么不保留共性信息。

unsorted_df$commonality <- colSums(sapply(1:nrow(unsorted_df), function(y){
                                   sapply(1:ncol(unsorted_df), function(x){ 
                           colSums(unsorted_df)[x] > 1 & unsorted_df[y,x]})}))
unsorted_df
#   c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 commonality
#1   1  1  1  0  0  0  1  0  0   0   0   0           3
#2   0  0  0  0  0  0  0  0  1   1   1   1           0
#3   0  1  1  1  0  0  0  0  0   0   0   0           2
#4   0  0  0  0  0  1  1  0  0   0   0   0           2
#5   0  0  0  0  0  1  0  0  0   0   0   0           1
#6   0  0  0  0  0  1  0  0  0   0   0   0           1
#7   0  0  0  0  0  1  0  1  0   0   0   0           1
#8   0  0  0  0  0  1  0  0  0   0   0   0           1
#9   0  0  0  0  0  1  1  0  0   0   0   0           2
#10  0  0  0  0  0  0  0  0  0   0   0   0           0

(sorted_df <- unsorted_df[order(unsorted_df[,"commonality"], decreasing=TRUE),])
#   c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 commonality
#1   1  1  1  0  0  0  1  0  0   0   0   0           3
#3   0  1  1  1  0  0  0  0  0   0   0   0           2
#4   0  0  0  0  0  1  1  0  0   0   0   0           2
#9   0  0  0  0  0  1  1  0  0   0   0   0           2
#5   0  0  0  0  0  1  0  0  0   0   0   0           1
#6   0  0  0  0  0  1  0  0  0   0   0   0           1
#7   0  0  0  0  0  1  0  1  0   0   0   0           1
#8   0  0  0  0  0  1  0  0  0   0   0   0           1
#2   0  0  0  0  0  0  0  0  1   1   1   1           0
#10  0  0  0  0  0  0  0  0  0   0   0   0           0

<强>解释

对于每一行y,请浏览每一列x,如果该列的总和大于1且该点的值不是0,{ {1}},NANULL填写新矩阵并将该点定义为FALSE,所有其他点均为TRUE

这将创建FALSE / TRUE条目的转置矩阵。

此新矩阵的列(FALSE = 1,TRUE = 0)的总和是每行的FALSE值。

答案 3 :(得分:0)

这是我如何使用dplyr来做到这一点。 逐步运行链式命令以检查每个步骤后的输出。 你或许可以改进它。

library(dplyr)

# example dataset
dt = data.frame(x1=c(1,1,0,0),
                x2=c(1,1,1,1),
                x3=c(0,1,0,1))

看起来像这样,我们使用行

 x1 x2 x3
1  1  1  0
2  1  1  1
3  0  1  0
4  0  1  1

然后我们

# give an id to each user (row)
dt = dt %>% mutate(id=row_number())

expand.grid(dt$id,dt$id) %>% # create all combinations of user ids
  data.frame() %>% 
  filter(Var1 != Var2) %>% # exclude users paired with themseves
  left_join(dt, by=c("Var1"="id")) %>% # join actual rows
  left_join(dt, by=c("Var2"="id")) %>% # join actual rows
  select(-Var1,-Var2) %>% # remove ids
  group_by(x1.x, x2.x, x3.x, x1.y, x2.y, x3.y) %>% # group by combination of users' rows
  do(data.frame(score=sum(.[1:3]*.[4:6])/sqrt(sum(.[1:3]^2)*sum(.[4:6]^2)))) %>% # create cosine similarity per row
  group_by(x1.x, x2.x, x3.x) %>% # group per user's row
  summarise(MeanScore = mean(score),
            MaxScore = max(score),
            MedianScore = median(score)) %>%
  ungroup

最终输出提供每行(用户)的得分分布的摘要统计信息,可用于排名

  x1.x x2.x x3.x MeanScore  MaxScore MedianScore
1    0    1    0 0.6638546 0.7071068   0.7071068
2    0    1    1 0.6745345 0.8164966   0.7071068
3    1    1    0 0.6745345 0.8164966   0.7071068
4    1    1    1 0.7367811 0.8164966   0.8164966

不需要使用dplyr的for循环。 在&#34;做&#34;内部还有一些工作要做。命令自动化过程,但如果您使用初始数据集的用户(行)数量,则很容易。