Pour pouvoir utiliser Python
dans Rmarkdown
il faut utiliser le package reticulate
. On peut lui préciser le chemin de la version que l’on veut utiliser une certaine version plutôt que celle par défaut. Si une version de Python
est déjà chargée, il faut relancer la session R
pour que la modification soit appliqué.
library(reticulate)
use_virtualenv("r-reticulate")
::py_config() reticulate
## python: /usr/share/miniconda/envs/finistR2020/bin/python3
## libpython: /usr/share/miniconda/envs/finistR2020/lib/libpython3.8.so
## pythonhome: /usr/share/miniconda/envs/finistR2020:/usr/share/miniconda/envs/finistR2020
## version: 3.8.5 | packaged by conda-forge | (default, Aug 29 2020, 01:22:49) [GCC 7.5.0]
## numpy: /usr/share/miniconda/envs/finistR2020/lib/python3.8/site-packages/numpy
## numpy_version: 1.19.1
##
## python versions found:
## /usr/share/miniconda/envs/finistR2020/bin/python3
## /usr/bin/python3
## /usr/bin/python
Il suffit alors de créer un chunk avec python
comme langage. Tous les objets R
de l’environnement sont accessible via la commande r.
.
= 2
x print(x)
## 2
= x r.x
Dans un chunk R
, les objets python
sont accessible avec la commande py$
.
py$x
x <- x**2
y <-print(y)
## [1] 4
typeof(y)
## [1] "double"
Il faut faire attention à la transformation automatique des types de R
vers python
, ce dernier étant plus pointilleux que R
la dessus.
= [i**2 for i in range(int(r.y))]
z
print(z)
## [0, 1, 4, 9]
graph_tool
est une librairie python
pour analyser des réseaux développer par T. Peixoto. Elle permet entre autre de faire des visualisations interactive de graphes et est également très réputée pour ces implémentations du SBM et du degree corrected SBM.
library(sbm)
library(igraph)
library(tidyverse)
import graph_tool.all as gt
import matplotlib.pyplot as plt
import numpy as np
import math
import time
= gt.collection.data["football"]
g print(g)
## <Graph object, undirected, with 115 vertices and 613 edges, 4 internal vertex properties, 2 internal graph properties, at 0x7fe89413f190>
= gt.minimize_blockmodel_dl(g)
state = state.get_matrix() m
Les plots matplotlib
sortent très bien dans le notebook, mais ce n’est pas le cas des plots interactifs. Ceux-ci ouvrent une fenêtre python
interactive et bloquent la compilation du document.
plt.matshow(m.todense())
Si l’on décide de sortir un plot inline, la fenêtre virtuelle ne s’ouvre pas et l’on récupère juste l’adresse mémoire du graph stocker. Il faut sauver dans un fichier et insérer “à la main”
= None
pv for i in range(1000):
= state.mcmc_sweep(niter=10)
ret = state.collect_vertex_marginals(pv)
pv gt.mf_entropy(g, pv)
## 3.101857666590992
= gt.graph_draw(g, pos=g.vp["pos"], vertex_shape="pie",
p =pv, inline= True, output = "img/hier.png") vertex_pie_fractions
On obtient des représentations graphiques sur des graph assez gros (1500 noeuds) rapidement.
= gt.price_network(1500)
g = g.degree_property_map("in")
deg = 4 * (np.sqrt(deg.a) * 0.5 + 0.4) deg.a
= gt.betweenness(g)[1]
ebet /= ebet.a.max() / 10.
ebet.a = ebet.copy()
eorder *= -1
eorder.a = gt.sfdp_layout(g)
pos = g.new_edge_property("vector<double>")
control for e in g.edges():
= np.sqrt(sum((pos[e.source()].a - pos[e.target()].a) ** 2)) / 5
d = [0.3, d, 0.7, d]
control[e] =pos, vertex_size=deg, vertex_fill_color=deg, vorder=deg,
gt.graph_draw(g, pos=ebet, eorder=eorder, edge_pen_width=ebet,
edge_color=control, # some curvy edges
edge_control_points="img/graph-draw.png") output
## <VertexPropertyMap object with value type 'vector<double>', for Graph 0x7fe892d59790, at 0x7fe892d50970>
Et l’on peut également sortir des plots interactifs avec graphviz.
= gt.price_network(1500)
g = g.degree_property_map("in")
deg = 2 * (np.sqrt(deg.a) * 0.5 + 0.4)
deg.a = gt.betweenness(g)[1]
ebet #gt.graphviz_draw(g, vcolor=deg, vorder=deg, elen=10,
# ecolor=ebet, eorder=ebet, )#, output="graphviz-draw.pdf")
= gt.price_network(3000)
g = gt.sfdp_layout(g)
pos =pos)#, output="graph-draw-sfdp.pdf") gt.graph_draw(g, pos
= gt.collection.data["netscience"]
g = gt.GraphView(g, vfilt=gt.label_largest_component(g))
g
g.purge_vertices()= gt.minimize_nested_blockmodel_dl(g, deg_corr=True)
state = gt.get_hierarchy_tree(state)[0]
t = pos = gt.radial_tree_layout(t, t.vertex(t.num_vertices() - 1), weighted=True)
tpos = gt.get_hierarchy_control_points(g, t, tpos)
cts = g.own_property(tpos)
pos = state.levels[0].b
b = b.copy()
shape %= 14
shape.a =pos, vertex_fill_color=b, vertex_shape=shape,
gt.graph_draw(g, pos=cts,
edge_control_points=[0, 0, 0, 0.3], vertex_anchor=0)#, output="netscience_nested_mdl.pdf") edge_color
Un essaie de plot hiérarchique:
= gt.collection.data["celegansneural"]
g = gt.minimize_nested_blockmodel_dl(g, deg_corr=True)
state ="img/celegansneural_hier.png") gt.draw_hierarchy(state, output
## (<VertexPropertyMap object with value type 'vector<double>', for Graph 0x7fe892d326a0, at 0x7fe892cecac0>, <Graph object, directed, with 317 vertices and 316 edges, at 0x7fe892d4cc40>, <VertexPropertyMap object with value type 'vector<double>', for Graph 0x7fe892d4cc40, at 0x7fe892d59d90>)
Si l’on fit un sbm sur un graph, l’autoplot sur l’état des blocks du graphe se fait automatiquement.
= time.time()
t0 = gt.collection.data["polbooks"]
g
= gt.minimize_blockmodel_dl(g , deg_corr=False)
state for i in range(10):
= gt.minimize_blockmodel_dl(g , deg_corr=False)
s if s.entropy() < state.entropy():
= s
state
= t0 - time.time()
t print(t)
## -16.440711975097656
state.entropy()
## 1321.9479136333077
=g.vp["pos"], vertex_shape=state.get_blocks(), output="img/polbooks_blocks_mdl.svg") state.draw(pos
## <VertexPropertyMap object with value type 'vector<double>', for Graph 0x7fe892cec760, at 0x7fe892cecc70>
python
à R
On peut passer le réseau via la matrice d’adjacence de python
à R
, mais on aimerait mieux sortir un objet graphml
qui est bien lu par igraph
.
Malheureusement, cela ne fonctionne pas. Toutes les méthodes de graph_tool
sur les noeuds et les arêtes renvoient des itérateurs. Il est nécessaire de les transformer en vecteur avec de les utiliser en R
.
= [b for b in state.get_blocks()]
blocks = gt.adjacency(g)
A ## g.save(file_name= "/home/stc/Documents/StateOfTheR/FinistR2020/graph_gt.graphml", fmt="graphml")
$blocks + 1 py
## [1] 1 1 6 2 6 1 1 6 2 1 2 2 2 2 1 3 3 3 1 3 1 3 1 3 1 1 1 3 4 1 5 5 3 3 3 3 3
## [38] 3 3 3 2 3 3 3 3 1 3 2 1 6 1 6 6 1 3 3 3 1 6 4 4 4 4 4 6 6 5 6 6 6 4 5 5 5
## [75] 5 5 5 4 4 4 4 4 4 4 5 6 5 4 4 4 4 4 4 4 4 4 4 4 4 5 5 4 4 6 6
as.matrix(py$A)
A <-isSymmetric(A)
## [1] TRUE
blockmodels::BM_bernoulli("SBM_sym", A, verbosity = 0, plotting = "") my_sbm <-
Sys.time()
t0 <-$estimate() my_sbm
t0 - Sys.time()
t <- t
## Time difference of -6.823365 secs
::ARI(c1 = py$blocks +1, c2 = my_sbm$memberships[[5]]$map()$C) aricode
## [1] 0.7586591
$memberships[[5]]$map()$C my_sbm
## [1] 3 3 3 2 3 3 3 3 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 4 3 5 5 1 1 1 1 1
## [38] 1 1 1 2 1 1 1 1 1 1 2 1 3 1 3 3 1 1 1 1 1 3 4 4 4 4 4 3 3 5 3 3 3 4 5 5 5
## [75] 5 5 5 4 4 4 4 4 4 4 5 3 5 4 4 4 4 4 4 4 4 4 4 4 4 5 5 4 4 3 3
$blocks +1 py
## [1] 1 1 6 2 6 1 1 6 2 1 2 2 2 2 1 3 3 3 1 3 1 3 1 3 1 1 1 3 4 1 5 5 3 3 3 3 3
## [38] 3 3 3 2 3 3 3 3 1 3 2 1 6 1 6 6 1 3 3 3 1 6 4 4 4 4 4 6 6 5 6 6 6 4 5 5 5
## [75] 5 5 5 4 4 4 4 4 4 4 5 6 5 4 4 4 4 4 4 4 4 4 4 4 4 5 5 4 4 6 6
Les clustering obtenus par graph-tool
et sbm (blockmodels
) sont très proche pour le sbm simple.
::graph_from_adjacency_matrix(
igraphmode = "directed") %>% igraph::write_graph(file = "graph_test.graphml", format = "graphml") A,
= gt.load_graph(file_name="~/Documents/StateOfTheR/FinistR2020/graph_test.graphml", fmt="graphml") gr
= False
gr.set_directed =False) gt.minimize_blockmodel_dl(gr, deg_corr
python
vers R
. Une solution serait peut-être d’utiliser le module igraph
de python
.python
pour la mettre dans la sortie html du rmarkdown
?