我想要什么
我有一个daframe,前两列是 m 字符串值的组合。这些值是用户ID,数据框表示它们之间的关系。每行包括用户标准( user1 , user2 )以及 user1 访问 user2 的次数轮廓。 m 有不同的用户,但每个可能的关系都没有行,仅适用于访问过其他人的个人资料的人。相互配对可以有不同的值,甚至不存在(如果 user1 已经访问了 user2 的配置文件,但没有相反的方式)。
我想创建我的数据框的简化版本,更容易使用。因此,我想提取至少 r 关系的 n 用户组( n < m )之间。我需要开发一个函数来检查是否至少存在 r 行(关系),任何 n 用户组合( n < ; m )。如果是,则该函数返回由它们形成的数据帧。 也就是说,该函数应返回符合以下要求的daframe(让我们将其命名为 S ):
小例子
这是一个最小的示例,其中用户ID只是一个字母。有5个不同的用户(a,b,c,d,e)和它们之间的10个关系:
>df
user1 user2 views
1 a b 1
2 a c 1
3 a d 3
4 b a 1
5 c b 1
6 c d 2
7 c e 4
8 d a 5
9 d e 1
10 d c 2
对于 r = 8 n = 4,我尝试提取一组4个用户,他们之间至少有8个关系。输出应该是8行的数据帧,前两列中只包含4个不同的 user 值(如果有的话)。有5种不同的4用户组合,其值高于[(a,b,c,d),(a,b,c,e),(a,b,d,e),(a,c,d, e),(b,c,d,e)]。然而,只有其中一个(a,b,c,d)包括成员之间的8个关系。输出应该是:
[1] "a" "b" "c" "d"
user1 user2 views
1 a b 1
2 a c 1
3 a d 3
4 b a 1
5 c b 1
6 c d 2
7 d a 5
8 d c 2
对于 r = 6 n = 4,目的是找到一组4个用户,他们之间有6个关系。在这种情况下,有2个4用户组合满足形成至少6行[(a,b,c,d),(a,c,d,e)]的要求。输出可以是以下任何一种:
[1] "a" "b" "c" "d"
user1 user2 views
1 a b 1
2 a c 1
3 a d 3
4 b a 1
5 c b 1
6 c d 2
7 d a 5
8 d c 2
[1] "a" "c" "d" "e"
user1 user2 views
1 a c 1
2 a d 3
3 c d 2
4 c e 4
5 d a 5
6 d c 2
7 d e 1
r > 8,没有4用户组合有效。没有4个用户组,它们之间的关系超过8个。然后,输出应为NULL
。
解决方案(如果数据框很小)
小数据帧的解决方案(适用于这个最小的例子)可以是获得所有可能的n用户组合并迭代它们,检查其中一个是否满足在df中形成r关系的要求。代码可能是这样的:
library(dplyr)
library(trotter)
obtainUserGroup <- function(df,n,r){
## Get unique letter _users_ in dataframe
us <- unique(append(df$user1,df$user2))
## All possible combinations of users in _us_ in groups of _n_ users
users <- cpv(n,us)
## Iterate over any possible group of _n_ users
for(i in 1:NROW(users)){
l <- as.character(users[i])
l <- as.data.frame(permutations(n,2,l),stringAsFactors=FALSE)
names(l) <- c("user1","user2")
# Check which combinations in l are part of df
dc <- semi_join(df,l,by = c("user1", "user2"))
if(NROW(dc) >= r) return(dc)
}
return(NULL)
}
df <- data.frame(c("a","a","a","b","c","c","c","d","d","d"), c("b","c","d","a","b","d","e","a","e","c"), c(1,1,3,1,1,2,4,5,1,2), stringsAsFactors=FALSE)
names(df) <- c("user1","user2","views")
n <- 4
r <- 8
obtainUserGroup(df,n,r)
问题
我的用户数据框非常大。尝试将包括数千名用户( m > 7000)用户的数据帧减少到只有一百或几百( n &lt;&lt; m )很麻烦。迭代可能的组合数是不可行的。
是否可以以与for-loop不同(更快)的方式检查所有组合? 有没有其他方法来解决这个问题,不同于检查所有可能的组合?