Search code examples
rdataframecombn

Finding network links from cluster information


I have network data that looks like this:

data <- data.frame(id = as.character(1:20),
                   cluster = sample(c("a", "b", "c"), 20, replace = T)) 
head(data)

# id cluster
# 1       b
# 2       b
# 3       c
# 4       a
# 5       c
# 6       a
# 7       a

In the past, I've successfully gotten cluster data from links, but not the other way around. I tried using the igraph package for network analysis but couldn't find a function that gave me a satisfactory result, and I didn't want to rely on a loop since they're inefficient and I in general try to stay away from them.

Expected Result

I'm wondering if there's an efficient way to create a new data.frame with all possible "links" within a cluster, so that I end up with a data.frame that looks like:

id1 id2 cluster
4   6       a
7   4       a
7   6       a
1   2       b
3   5       c

Solution

  • You can do this in :

    set.seed(123)
    data <- data.frame(id = as.character(1:20),
                       cluster = sample(c("a", "b", "c"), 20, replace = T))
    
    library(data.table)
    setDT(data)[, id:=as.character(id)][, t(combn(id, 2, FUN = list)), by = cluster]
    
    #>     cluster V1 V2        #>     cluster V1 V2        #>     cluster V1 V2    
    #>  1:       a  1 17        #> 21:       c 12  8        #> 41:       c  5  8    
    #>  2:       a  1  7        #> 22:       c 12 13        #> 42:       c  5 13    
    #>  3:       a  1  9        #> 23:       c 15 16        #> 43:       c  8 13    
    #>  4:       a  1 10        #> 24:       c 15 19        #> 44:       b 14 18    
    #>  5:       a  1 11        #> 25:       c 15  3        #> 45:       b 14 20    
    #>  6:       a 17  7        #> 26:       c 15  5        #> 46:       b 14  2    
    #>  7:       a 17  9        #> 27:       c 15  8        #> 47:       b 14  4    
    #>  8:       a 17 10        #> 28:       c 15 13        #> 48:       b 14  6    
    #>  9:       a 17 11        #> 29:       c 16 19        #> 49:       b 18 20    
    #> 10:       a  7  9        #> 30:       c 16  3        #> 50:       b 18  2    
    #> 11:       a  7 10        #> 31:       c 16  5        #> 51:       b 18  4    
    #> 12:       a  7 11        #> 32:       c 16  8        #> 52:       b 18  6    
    #> 13:       a  9 10        #> 33:       c 16 13        #> 53:       b 20  2    
    #> 14:       a  9 11        #> 34:       c 19  3        #> 54:       b 20  4    
    #> 15:       a 10 11        #> 35:       c 19  5        #> 55:       b 20  6    
    #> 16:       c 12 15        #> 36:       c 19  8        #> 56:       b  2  4    
    #> 17:       c 12 16        #> 37:       c 19 13        #> 57:       b  2  6    
    #> 18:       c 12 19        #> 38:       c  3  5        #> 58:       b  4  6    
    #> 19:       c 12  3        #> 39:       c  3  8            
    #> 20:       c 12  5        #> 40:       c  3 13            
    

    or in :

    set.seed(123)
    data <- data.frame(id = as.character(1:20),
                       cluster = sample(c("a", "b", "c"), 20, replace = T))
    
    library(dplyr)
    data %>% group_by(cluster) %>% mutate(id=as.character(id)) %>% 
             do(data.frame(t(combn(.$id, 2))))
    
    #> # A tibble: 58 x 3
    #> # Groups:   cluster [3]
    #>    cluster    X1    X2
    #>    <fct>   <dbl> <dbl>
    #>  1 a           1    17
    #>  2 a           1     7
    #>  3 a           1     9
    #>  4 a           1    10
    #>  5 a           1    11
    #>  6 a          17     7
    #>  7 a          17     9
    #>  8 a          17    10
    #>  9 a          17    11
    #> 10 a           7     9
    #> # ... with 48 more rows
    

    Created on 2019-05-16 by the reprex package (v0.2.1)