在两行不为零的情况下,用于选择行的列的成对比较

时间:2017-11-02 14:27:49

标签: r dataframe matrix subset

考虑以下矩阵/ data.frame和vector:

set.seed(123)
data<-data.frame(lorem=floor(runif(26, min=0, max=10)),
                    ipsum=floor(runif(26, min=0, max=10)),
                        dolor=floor(runif(26, min=0, max=10)))

topicVector<-c(1,2,12,13,14,15,18,22,23,31 ,36 ,40 ,44 
             ,54,58,59,73,100,101,104,107,108,111,113,114,116)

注意:topicVector也可能是data的一部分,因为它们的长度相等。

我的目标是对data中列的所有唯一组合进行成对比较,然后将其转换为长数据框架,其中列出topicVector中作为非索引的所有数字。 data中的列共享的零行。

即。结果data.frame中的每一行应该是一个可能的列组合:例如来自lorem的{​​{1}}和ipsumdata中的数字是指topics中包含非零条目且来自data的行。 我们来看看topicVector和“pps lorem数据”(第一个组合)

from

在上面针对 lorem ipsum 1 2 5 2 7 5 3 4 2 4 8 1 5 9 9 6 0 9 7 5 6 8 8 7 9 5 0 10 4 4 11 9 7 12 4 2 13 6 3 14 5 2 15 1 1 16 8 4 17 2 4 18 0 3 19 3 1 20 9 1 21 8 2 22 6 4 23 6 2 24 9 8 25 6 0 26 7 4 lorem的示例中,行1,2和3包含两个数字,即共享主题。根据主题向量,这是主题1,2和12.在第4行中,ipsum为0,因此它们不共享该主题,主题13不是结果data.frame的一部分。 他们总共分享了多个主题(18)。

如果没有共享主题(即所有行= 0),结果df中的ipsum对于这对列应该包含0。

上述结果应如下所示:

topics

我在R中写了一个功能来完成这项工作。然而,原始数据略大(1000列), user1 user2 topics 1 lorem ipsum 1 2 lorem ipsum 2 3 lorem ipsum 12 4 lorem ipsum 13 5 lorem ipsum 14 6 lorem ipsum 18 7 lorem ipsum 22 8 lorem ipsum 31 9 lorem ipsum 36 10 lorem ipsum 40 11 lorem ipsum 44 12 lorem ipsum 54 13 lorem ipsum 58 14 lorem ipsum 59 15 lorem ipsum 73 16 lorem ipsum 101 17 lorem ipsum 104 18 lorem ipsum 107 19 lorem ipsum 108 20 lorem ipsum 111 21 lorem ipsum 113 22 lorem ipsum 116 23 lorem dolor 1 24 lorem dolor 2 25 lorem dolor 12 26 lorem dolor 13 27 lorem dolor 14 28 lorem dolor 18 29 lorem dolor 22 30 lorem dolor 23 31 lorem dolor 36 32 lorem dolor 40 33 lorem dolor 44 34 lorem dolor 54 35 lorem dolor 58 36 lorem dolor 59 37 lorem dolor 73 38 lorem dolor 101 39 lorem dolor 104 40 lorem dolor 107 41 lorem dolor 111 42 lorem dolor 113 43 lorem dolor 114 44 lorem dolor 116 45 ipsum dolor 1 46 ipsum dolor 2 47 ipsum dolor 12 48 ipsum dolor 13 49 ipsum dolor 14 50 ipsum dolor 15 51 ipsum dolor 18 52 ipsum dolor 22 53 ipsum dolor 36 54 ipsum dolor 40 55 ipsum dolor 44 56 ipsum dolor 54 57 ipsum dolor 58 58 ipsum dolor 59 59 ipsum dolor 73 60 ipsum dolor 100 61 ipsum dolor 101 62 ipsum dolor 104 63 ipsum dolor 107 64 ipsum dolor 111 65 ipsum dolor 113 66 ipsum dolor 116 非常慢。

listCommonTopics

我的问题是:

  1. 为什么我的版本速度慢?我知道嵌套的for循环不是 最好的主意,但即使几个小时后我也没有结果。
  2. 矢量化矩阵版本(应用)是什么样的?
  3. 是否也可以使用listCommonTopics<-function(data,topicVector){ result_df<-data.frame(user1=character(), user2=character(), topics=numeric(),stringsAsFactors = FALSE) for(i in seq_along(data)){ print(i) for(j in seq_along(data)){ if(j>i){ if(colnames(data[i])!=colnames(data[j])){ compareUsers<-data.frame(topicVector,data[,i],data[,j],stringsAsFactors = FALSE) commonTopics<-subset(compareUsers,compareUsers[,2]!=0&compareUsers[,3]!=0) if(nrow(commonTopics)==0){ user1<-rep(colnames(data[i]),1) user2<-rep(colnames(data[j]),1) topics<-0 }else{ user1<-rep(colnames(data[i]),nrow(commonTopics)) user2<-rep(colnames(data[j],nrow(commonTopics))) topics<-commonTopics[,1] } pairwise_df<-data.frame(user1=user1,user2=user2,topics=topics,stringsAsFactors = FALSE) result_df<-rbind(result_df,pairwise_df) } } } } return(result_df) } 完成?

1 个答案:

答案 0 :(得分:0)

试试这个:

do.call(rbind,
        lapply(combn(names(data), 2, simplify = FALSE),
               function(x) {
                 test <- Reduce("*", data[, x]) != 0
                 data.frame(setNames(as.list(x), c("user1", "user2")), 
                                      topics = if (any(test)) topicVector[test] else 0)
                 })
)

  • 在列表中创建列名的所有组合,
  • 遍历该列表,
  • 检查两列中的产品(使用Reduce("*", inputList)构造计算)是否为零,并将其用于对主题向量进行子集化,
  • 将结果与do.call(rbind, listOfResults)构造结合起来。