美文网首页网络分析
网络数据统计分析笔记|| 操作网络数据

网络数据统计分析笔记|| 操作网络数据

作者: 周运来就是我 | 来源:发表于2020-09-24 22:42 被阅读0次

    前情回顾:
    Gephi网络图极简教程
    Network在单细胞转录组数据分析中的应用
    网络数据统计分析笔记|| 为什么研究网络

    书接上回,我们来看看如何构建网络以及可以对网络做的基本操作,主要用的R包是igraph。

    • 创建网络图
    • 图的表示
    • 图的增删
    • 图的修饰
    • 图的属性

    igraph是一个用于创建和操作图以及分析网络的R包。它是用C编写的,也以Python和R包的形式存在。此外,还存在一个Mathematica接口。该软件广泛应用于网络科学及相关领域的学术研究。据谷歌Scholar统计,截止2015年6月5日,介绍该软件的出版物有5623次引用。

    创建网络图

    网络用节点描述元素,用连线描述元素间关系。一个图G = (V,E)是包含节点V(vertices ,nodes)集合与边E(edges ,links)集合的数学结构。其中节点数N_v = |V|称为图G的阶数(order),边的数量N_e= |E|称为图G的规模(size)。

    在创建图之前我们来认识一下igraph包。

    # install.packages("pacman")
    rm(list = ls())
    library(sand)
    
    # CHUNK 1
    library(igraph)
    library(pacman)
    length(p_functions(igraph))
    [1] 784
     grep('graph_from',p_functions(igraph),value = T)
     [1] "graph_from_adj_list"          "graph_from_adjacency_matrix"  "graph_from_atlas"            
     [4] "graph_from_data_frame"        "graph_from_edgelist"          "graph_from_graphdb"          
     [7] "graph_from_graphnel"          "graph_from_incidence_matrix"  "graph_from_isomorphism_class"
    [10] "graph_from_lcf"               "graph_from_literal"          
    

    可以看到igraph 共有 784个函数,其中读入数据的有11个,功能可谓是全的很啊。我们先从最简单的做起,构建一个手写的图:

    g <- graph_from_literal(1-2, 1-3, 2-3, 2-4, 3-5, 4-5, 
                        4-6, 4-7, 5-6, 6-7)
    
    plot(g)
    

    查看图的属性

     V(g)
    + 7/7 vertices, named, from e2c1098:
    [1] 1 2 3 4 5 6 7
    
     E(g)
    + 10/10 edges from e2c1098 (vertex names):
     [1] 1--2 1--3 2--3 2--4 3--5 4--5 4--6 4--7 5--6 6--7
    
     print_all(g)
    IGRAPH e2c1098 UN-- 7 10 -- 
    + attr: name (v/c)
    + edges (vertex names):
    1 -- 2, 3
    2 -- 1, 3, 4
    3 -- 1, 2, 5
    4 -- 2, 5, 6, 7
    5 -- 3, 4, 6
    6 -- 4, 5, 7
    7 -- 4, 6
    

    在g的结构描述中,字母U表示该图是无向的(undirected),即一条边的两个节点没方向和次序。简单有向图可以这样构建:

    dg <- graph_from_literal(1-+2, 1-+3, 2++3)
    plot(dg)
    

    要想使图有意义,我们就需要给图起名字:

     par(mfrow=c(1,3))
    dg <- graph_from_literal(1-+2, 1-+3, 2++3)
    plot(dg)
    dg <- graph_from_literal(Sam-+Mary, Sam-+Tom, 
    +                           Mary++Tom)
     print_all(dg)
    
    IGRAPH ea00245 DN-- 3 4 --  # UN 变成DN
    + attr: name (v/c)
    + edges from ea00245 (vertex names):
    [1] Sam ->Mary Sam ->Tom  Mary->Tom  Tom ->Mary
    
     plot(dg)
    
    V(dg)$name <- c("Sam1", "Mary1", "Tom_1")
    
    E(dg)
    + 4/4 edges from ea00245 (vertex names):
    [1] Sam1 ->Mary1 Sam1 ->Tom_1 Mary1->Tom_1 Tom_1->Mary1
    > # ---
    > ## + 4/4 edges from 062bf79 (vertex names):
    > ## [1] Sam ->Mary Sam ->Tom  Mary->Tom  Tom ->Mary
    > # ---
     plot(dg)
    

    我们无法想象手动用+-号来构建一个成千上百的网络图,一般的图都是在数据文件里,存在三种表示图的格式:

    • 邻接列表
    • 边列表
    • 邻接矩阵

    邻接表(graph_adjacency_list):邻接表是图的一种链式存储结构。在邻接表中,对图中每一个顶点建立一个单链表,第i个单链表中的节点表示依附于顶点vi的边(对有向图是以顶点vi为尾的弧)。每一个结点有三个域组成,当中邻接点域指示与顶点vi邻接的点在途中的位置,链域指示下一条边或者弧的结点;数据域存储和边或者弧相关的信息。如权值等。每一个链表上附设一个表头结点。

    边列表简单来说就是边跟边的两个顶点。

     E(dg)
    + 4/4 edges from ea00245 (vertex names):
    [1] Sam1 ->Mary1 Sam1 ->Tom_1 Mary1->Tom_1 Tom_1->Mary1
    

    图的邻接矩阵存储方式是用两个数组来表示图。一个一维数组存储图中顶点信息,一个二维数组(邻接矩阵)存储图中的边或弧的信息。
    设图G有n个顶点,则邻接矩阵是一个n*n的方阵,定义为:


    as_adjacency_matrix(dg)
    3 x 3 sparse Matrix of class "dgCMatrix"
          Sam1 Mary1 Tom_1
    Sam1     .     1     1
    Mary1    .     .     1
    Tom_1    .     1     .
    

    三者之间的对应 关系可以用下图表示:

    鉴于矩阵是多数编程语言的基本数据对象,邻接矩阵经常作为网络图的存储方式。但是如果是大型的网络,如果不转化为稀疏矩阵,一般的矩阵会非常低效。在文章的开头我们展示了几个其他数据读入igraph的函数,以生成对应的网络。read_graph函数能够从文件或http连接读取各种表示形式的图形。

    igraph绘制的网络图导入到gephi

     install and load
    install.packages("rgexf", dependencies=TRUE)
    library(rgexf)  
    cg1 <- erdos.renyi.game(10, 0.8)
    nodes <- data.frame(cbind(V(cg1), as.character(V(cg1))))
    edges <- t(Vectorize(get.edge, vectorize.args='id')(cg1, 1:ecount(cg1)))
    write.gexf(nodes, edges) 
    
    
    图的表示

    刚生成或者导入的图可能不是我们需要的图,对图的各种操作不可或缺,包括取子图、删节点,增加边,甚至是合并图。在一张图上有了感兴趣的区域,我们一般会采取取子图的操作,子图的定义是某图的边和点均来自母图。如取g前5个节点的子图:

     h <- induced_subgraph(g, 1:5)
    print_all(h)
    IGRAPH ae29f26 UN-- 5 6 -- 
    + attr: name (v/c)
    + edges from ae29f26 (vertex names):
    [1] 1--2 1--3 2--3 2--4 3--5 4--5
     plot(h)
    

    G= (V,E)中节点和边的纳入与删除,可以通过对集合VE使用加号或减号操作符实现。上面的图可以:

    h <- g - vertices(c(6,7))
    print_all(h)
    plot(h)
    

    相似地,g也可以由h生成:

     h <- h + vertices(c(6,7))
     g <- h + edges(c(4,6),c(4,7),c(5,6),c(6,7))
    print_all(g)
    IGRAPH 77655ae UN-- 7 10 -- 
    + attr: name (v/c)
    + edges (vertex names):
    1 -- 2, 3
    2 -- 1, 3, 4
    3 -- 1, 2, 5
    4 -- 2, 5, 6, 7
    5 -- 3, 4, 6
    6 -- 4, 5, 7
    7 -- 4, 6
    plot(g)
    

    图的并,交,差,补。
    图的并集

    h1 <- h
    h2 <- graph_from_literal(4-6, 4-7, 5-6, 6-7)
    g <- graph.union(h1,h2)
    print_all(g)
    IGRAPH 1cc06a7 UN-- 7 10 -- 
    + attr: name (v/c)
    + edges (vertex names):
    1 -- 2, 3
    2 -- 1, 3, 4
    3 -- 1, 2, 5
    4 -- 2, 5, 6, 7
    5 -- 3, 4, 6
    6 -- 4, 5, 7
    7 -- 4, 6
    plot(g)
    
    网络图的修饰

    一幅图(graph,network)要有实际的意义,就要有与相应的网络图所关联的值。将一个图与这些属性(attributes)关联在一起的过程称为图的修饰(decorating)。在igraph中节点和边的属性可以通过$符号获得和修改。

    V(dg)$name
    [1] "Sam"  "Mary" "Tom" 
    V(dg)$gender <- c("M","F","M")
    
    V(g)$color <- c("red","blue")
    plot(g)
    
    

    也可以将某些计算的节点特征值用这种方式保存,并用于可视化化或者统计。

    同样地,边的属性用于描述元素之间的关系,如强弱,正负等。边的属性在在许多分析中可以认为是权重,有权重的图称为含权图(weighted graph)。

     is_weighted(g)
    [1] FALSE
    
    wg <- g
    E(wg)$weight <- runif(ecount(wg))
     is_weighted(wg)
    [1] TRUE
     plot(wg)
    

    其实图本身也可以有属性,如:

    g$name <- "Toy Graph"
    

    使用数据框

    大型的网络图不可能手动输入,而是采用数据框来存储和读入。igraph的节点和边属性可以存在节点和边文件的数据框中。

    library(sand)
    head(elist.lazega)
      V1  V2
    1 V1 V17
    2 V2  V7
    3 V2 V16
    4 V2 V17
    5 V2 V22
    6 V2 V26
    head(v.attr.lazega)
      Name Seniority Status Gender Office Years Age Practice School
    1   V1         1      1      1      1    31  64        1      1
    2   V2         2      1      1      1    32  62        2      1
    3   V3         3      1      1      2    13  67        1      1
    4   V4         4      1      1      1    31  59        2      3
    5   V5         5      1      1      2    31  59        1      2
    6   V6         6      1      1      2    29  55        1      1
    
    > g.lazega <- graph_from_data_frame(elist.lazega,
    +                                    directed="FALSE",
    +                                    vertices=v.attr.lazega)
    > g.lazega$name <- "Lazega Lawyers"
    > # CHUNK 21
    > vcount(g.lazega)
    [1] 36
    > # CHUNK 22
    > ecount(g.lazega)
    [1] 115
    > # CHUNK 23
    > vertex_attr_names(g.lazega)
    [1] "name"      "Seniority" "Status"    "Gender"    "Office"    "Years"     "Age"       "Practice"  "School"   
    > # ---
    > ## [1] "name"      "Seniority" "Status"    "Gender"   
    > ## [5] "Office"    "Years"     "Age"       "Practice" 
    > ## [9] "School"
    > # ---
    > plot(g.lazega)
    
    
    V(g.lazega)$color  = V(g.lazega)$Seniority
    plot(g.lazega)
    
    关于图

    简单图:在无向图中,关联一对顶点的无向边如果多于1条,则称这些边为平行边,平行边的条数称为重数。在有向图中,关联一对顶点的有向边如果多于1条,并且这些边的始点与终点相同(也就是它们的的方向相同),称这些边为平行边。含平行边的图称为多重图,既不含平行边也不包含自环的图称为简单图。

    is_simple(g)
    [1] TRUE
    

    构建多重图

    mg <- g + edge(2,3)
     is_simple(mg)
    [1] FALSE
        
    print_all(mg)
    plot(mg)
    

    在网络数据分析中,常需要将多重图转化为加权的简单图:

    E(mg)$weight <- 1
    # plot(mg)
    # ?simplify
    wg2 <- igraph::simplify(mg)
    is_simple(wg2)
    [1] TRUE
    
    print_all(wg2)
    IGRAPH c219b27 UNW- 7 10 -- 
    + attr: name (v/c), color (v/c), weight (e/n)
    + edges (vertex names):
    1 -- 2, 3
    2 -- 1, 3, 4
    3 -- 1, 2, 5
    4 -- 2, 5, 6, 7
    5 -- 3, 4, 6
    6 -- 4, 5, 7
    7 -- 4, 6
    
    E(wg2)$weight
     [1] 1 1 2 1 1 1 1 1 1 1
    
    plot(wg2)
    
    

    图的连通性,如果两个节点之间通过一条边链接,我们称两者是邻接的(adjacent),这些节点可以称为邻居(neighbors)。

    neighbors(g,5)
    
    + 3/7 vertices, named, from 1cc06a7:
    [1] 3 4 6
    

    类似地,两条边通过一个节点相连,称两者是邻接的。节点的度(degree)定义为其关联的边的数量。

    degree(g)
    1 2 3 4 5 6 7 
    2 3 3 4 3 3 2 
    

    如果是有向图,节点度可以进一步分为入度(in-degree)与出度(out-degree)分别代表指向与离开节点边的数量。

    degree(dg, mode="in")
     Sam Mary  Tom 
       0    2    2 
    
     degree(dg, mode="out")
     Sam Mary  Tom 
       2    1    1 
    
    

    描述图移动的概念:

    通路(walk)是一个节点和边交替的序列
    通路的长度length
    不存在重复边的通路为迹(trail)
    不存在重复节点的通路为路径(path)
    起点和终点相同的迹为回路(circuit)

    如果图G中存在节点u到另一个节点v的一条通路,则可称节点vu是可达的(reachable),若所有节点从任意节点均可达,则称图是连通的(connected)。图的组件(component)是一个最大化的连通子图。

    is_connected(g)
    [1] TRUE
    
     clusters(g)
    $membership
    1 2 3 4 5 6 7 
    1 1 1 1 1 1 1 
    
    $csize
    [1] 7
    
    $no
    [1] 1
    

    对于有向图,有弱连通和强连通之别:

     is_connected(dg,mode="weak")
    [1] TRUE
    
    is_connected(dg,mode="strong")
    [1] FALSE
    
    

    图中节点的距离(distance),被定义为节点间最短路径长度。图中最长的距离的值称为直径(diameter)

    diameter(g, weights=NA)
    [1] 3
    
    特殊类型的图
    g.full <- make_full_graph(7)
    g.ring <- make_ring(7)
    g.tree <- make_tree(7, children=2, mode="undirected")
    g.star <- make_star(7, mode="undirected")
    par(mfrow=c(2, 2), mai = c(0.2, 0.2, 0.2, 0.2))
    plot(g.full,main='compele graph')
    plot(g.ring,main= 'regular graph')
    plot(g.tree,main='tree')
    plot(g.star,main='star')
    

    一个无环的有向图称做有向无环图(directed acycline praph)。简称DAG 图。DAG 图是一类较有向树更一般的特殊有向图。

    is_dag(dg)
    [1] FALSE
    

    二分图又称作二部图,是图论中的一种特殊模型。 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图。

    g.bip <- graph_from_literal(actor1:actor2:actor3,
       movie1:movie2, actor1:actor2 - movie1,
       actor2:actor3 - movie2)
    V(g.bip)$type <- grepl("^movie", V(g.bip)$name)
    print_all(g.bip, v=T)
    
    IGRAPH f306940 UN-B 5 4 -- 
    + attr: name (v/c), type (v/l)
    + vertex attributes:
    |       name  type
    | [1] actor1 FALSE
    | [2] actor2 FALSE
    | [3] actor3 FALSE
    | [4] movie1  TRUE
    | [5] movie2  TRUE
    + edges from f306940 (vertex names):
    [1] actor1--movie1 actor2--movie1 actor2--movie2 actor3--movie2
    

    图的投影

    proj <- bipartite_projection(g.bip)
    print_all(proj[[1]])
    IGRAPH 9a82b4d UNW- 3 2 -- 
    + attr: name (v/c), weight (e/n)
    + edges from 9a82b4d (vertex names):
    [1] actor1--actor2 actor2--actor3
    
    print_all(proj[[2]])
    IGRAPH 9a82b4d UNW- 2 1 -- 
    + attr: name (v/c), weight (e/n)
    + edge from 9a82b4d (vertex names):
    [1] movie1--movie2
    
    
    par(mfrow=c(1, 3), mai = c(0.2, 0.2, 0.2, 0.2))
    plot(g.bip)
    plot(proj[[1]])
    plot(proj[[2]])
    

    https://igraph.org/r/
    存储在图的形式——邻接列表
    https://visualgo.net/zh/graphds
    https://gk.palem.in/iGraphExport.html
    https://www.cnblogs.com/alan-blog-TsingHua/p/10924894.html

    相关文章

      网友评论

        本文标题:网络数据统计分析笔记|| 操作网络数据

        本文链接:https://www.haomeiwen.com/subject/hexuyktx.html