具有r关系的n个用户的子集

时间:2016-07-13 08:10:37

标签: r dataframe unique

我想要什么

我有一个daframe,前两列是 m 字符串值的组合。这些值是用户ID,数据框表示它们之间的关系。每行包括用户标准( user1 user2 )以及 user1 访问 user2 的次数轮廓。 m 有不同的用户,但每个可能的关系都没有行,仅适用于访问过其他人的个人资料的人。相互配对可以有不同的值,甚至不存在(如果 user1 已经访问了 user2 的配置文件,但没有相反的方式)。

我想创建我的数据框的简化版本,更容易使用。因此,我想提取至少 r 关系的 n 用户组( n < m )之间。我需要开发一个函数来检查是否至少存在 r 行(关系),任何 n 用户组合( n < ; m )。如果是,则该函数返回由它们形成的数据帧。 也就是说,该函数应返回符合以下要求的daframe(让我们将其命名为 S ):

  • S 是原始数据框的子集
  • NROW(S)> = r
  • NROW(独特(追加(S [1],S [2])))= n

小例子

这是一个最小的示例,其中用户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不同(更快)的方式检查所有组合? 有没有其他方法来解决这个问题,不同于检查所有可能的组合?

0 个答案:

没有答案