寻找这个难题的聪明解决方案。我需要对下面的数据框进行排序,以便按最常见的行排序,其他行的值为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。所以没有基线,每一行都可以没有,一个或多个。我需要找到重叠最多的行,并将它们放在顶部以方便使用。
答案 0 :(得分:4)
这应该有效:
toSting()
不同行的相似度通过其乘积(内积,数学术语)的总和来计算。排序从第一行开始,保持不变。然后,下面附加下一个相似的行,并且已替换的行存储在用于替换的行的位置。
最终结果并不明确,因为可能会发生某行与尚未排序的任何其他行没有相似性。这种情况发生在例如第2行,并解释了看似不同的结果。
答案 1 :(得分:4)
好的,我想我得到的是OP。比较每个可能的行对,并调用给定的对R1
和R2
,如果执行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}},NA
或NULL
填写新矩阵并将该点定义为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;内部还有一些工作要做。命令自动化过程,但如果您使用初始数据集的用户(行)数量,则很容易。