martes, 27 de febrero de 2018

Visualización de redes de fotos de Facebook con Gephi y R

Recopilación de datos de Facebook y visualización de la red de fotos con Gephi y R

Katya Ognyanova



Visualizaciones en Gephi igraph qgraph

Recopilación y visualización de redes de Facebook utilizando las fotos de perfil de las personas como imágenes de nodo (de tres formas: con Gephi, igraph o qgraph): Obtenga aquí el script completo de R.


Gephi es una de mis herramientas de visualización de red favoritas: ofrece una amplia variedad de diseños personalizables, permite retoques sofisticados, hace que los gráficos grandes estén bien, trata con datos dinámicos y generalmente le permite producir resultados de aspecto elegante con un mínimo esfuerzo. Dicho esto, hay algunas cosas básicas (que casi cualquier otra herramienta de red puede hacer) que me he perdido en Gephi: como la capacidad de combinar diferentes formas de nodo y la opción de usar imágenes como nodos. La semana pasada, sin embargo, la buena gente de Yale Computer Graphics Group lanzó un plugin de Gephi que puede hacer exactamente eso. Se llama Vista previa de la imagen y le permitirá usar imágenes en su visita a la red Gephi.

Jugué un rato con el complemento para descubrir cómo funciona, y luego cambié a R para replicar los resultados que obtuve allí. Utilicé mi propia red de Facebook para este ejercicio, que facilitó la obtención de imágenes para cada nodo. Twitter habría funcionado igual de bien, pero también quería ver la nueva versión del paquete RFacebook. Pensé que compartiría los pasos para obtener los datos y visualizarlos (en Gephi, igraph o qgraph); resultó ser bastante sencillo con solo un par de fallas en el camino.

También debo señalar que se puede lograr el mismo efecto incluso más rápido usando cualquiera de las muchas aplicaciones de Facebook disponibles (por ejemplo, Bernie Hogan's NameGenWeb), o con el complemento de red NodeXL de Mark Smith para Excel.

Recopilando datos de Facebook



1 Registro. Lo primero que debe hacer es obtener los datos de Facebook. Antes de que se le permita sacarlo de R, tendrá que hacer un desvío rápido a developers.facebook.com/apps, registrarse como desarrollador y crear una nueva aplicación. El nombre y la descripción son irrelevantes, lo único que tienes que hacer es ir a Settings → Website → Site URL y completar http: // localhost: 1410 / (ese es el puerto que vamos a usar). Todo el proceso lleva ~ 5 min. Y es bastante sencillo. Si necesitas un tutorial más detallado, echa un vistazo a esta publicación de blog de Julian Hillebrand.


2 Autenticación. Ahora puedes ir a R, instalar el paquete de RFacebook y autenticarte con el ID y el secreto que se muestran en la pestaña Configuración de tu aplicación de Facebook.
Facebook authentication
01
02
03
04
05
06
07
08
install.packages("Rfacebook")
library(Rfacebook)
oauth <- fbOAuth(app_id = "your_app_id_here",
                 app_secret = "your_app_secret_here",
                 extended_permissions = T)
save(oauth, file="fb_oauth")
# load(file="fb_oauth")

3 Descarga de datos. En este punto, ya puede obtener información de Facebook. El uso de getFriends le dará un marco de datos que contiene (entre otras cosas) el nombre, nombre de usuario, género, ubicación, ciudad natal y URL de imagen de todos los contactos de Facebook que han proporcionado esa información. Puede usar getNetwork para recopilar los vínculos entre las personas en su lista de amigos, ya sea como una lista de bordes o como una matriz de adyacencia. Solo por el gusto de hacerlo (y porque no lleva mucho tiempo), conseguiremos los dos.
Collect friend info & network data from Facebook
09
10
11
12
13
14
# Get friend info:
my.friends <- getFriends(oauth, simplify=F)
# Get friend network in two formats, matrix and edge list:
fb.net.mat <- getNetwork(oauth, format="adj.matrix")+0 # bool,+0 to get numeric
fb.net.el  <- as.data.frame(getNetwork(oauth, format = "edgelist"))

4 Descarga de imagen. Usando las URL del marco de datos de amigos de Facebook, podemos descargar las fotos de perfil de las personas y almacenarlas en una carpeta local (aquí FBImages). La descarga en sí misma es simple con download.file: la mayoría de las líneas de scripts a continuación se ocupan de nombrar correctamente los archivos de imagen.
Download images from Facebook
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
setwd("C:/Research/R")
dir.create("FbImages")
# Image file name and local path stored here:
my.friends$picture.dld <- NA
# Download the images:
for (i in 1:dim(my.friends)[1]) {
  # Fb images appear to be mostly JPEGs, except for people
  # with no profile pics - for those we seem to get a default GIF
  pic.ext <- ".jpg"
  if(grepl(".gif$", my.friends$picture[i])) pic.ext <- ".gif"
  # We'll name files using people's full names plus file extension.
  my.friends$picture.dld[i] <-
                 paste0("FBImages/", sub(" ", "_", my.friends$name[i]), pic.ext)
  # Some users have UTF-8 encoded names that don't work well as file names:
  if (Encoding(my.friends$name[i])=="UTF-8") {
       my.friends$picture.dld[i] <-
                  paste0("FBImages/", "FbID_", my.friends$id[i], pic.ext) }
 download.file(my.friends$picture[i],  my.friends$picture.dld[i],  mode = 'wb')
}

Visualizando la red con Gephi

Hay varias maneras de mover datos de red de R a Gephi (ambos admiten varios formatos como gexf). Sin embargo, para redes simples / pequeñas, la forma más directa de exportar desde R es probablemente como CSV. Gephi necesita dos archivos CSV: uno que contenga una lista de bordes que describa cada enlace (las columnas que contienen el nodo de inicio y el nodo final para cada enlace deben llamarse Origen y Destino). El segundo archivo es una tabla de atributos de nodo: debe contener una columna llamada ID con identificadores de nodo correspondientes a los utilizados en Origen y Destino. Cualquier otro atributo generalmente es opcional, pero aquí debe tener una imagen llamada, que contenga los nombres de los archivos de fotos para que funcione el complemento de Vista previa de la imagen.
Export the network data for Gephi
39
40
41
42
43
44
colnames(fb.net.el) <- c("Source", "Target")
my.friends$ID <- my.friends$name
my.friends$image <- gsub("FBImages/(*.)", "\\1", my.friends$picture.dld)
  
write.csv(fb.net.el, file="Facebook-friend-EDGES.csv", row.names=F)
write.csv(my.friends, file="Facebook-friend-NODES.csv" row.names=F)

Después de importar los archivos (del Data Laboratory → Import Spreadsheet), puede retocar el diseño del gráfico en la pestaña Información general hasta que esté satisfecho con él, luego cambie a la pestaña Vista previa.

Si tiene instalado el complemento de Vista previa de imagen, debería ver una sección de Imágenes de nodo en la parte inferior de la barra de Configuración de vista previa del lado derecho. Marque Renderizar nodos como imágenes y especifique la carpeta donde se encuentran las fotos en el campo a continuación.



Gephi tomará los nombres de archivo almacenados en el atributo de nodo de imagen y los buscará en la ruta de la imagen que haya establecido. Una falla que encontré (que el creador del plugin Chris Xue amablemente ayudó) era que el complemento tenía problemas de compatibilidad con Java 7. Tuve que instalar Java 6 (descargar aquí) y cambiar la configuración de inicio de Gephi (en Gephi-0.8.2 \ etc \ gephi.conf cambiando el parámetro jdkhome) antes de que el complemento funcione.


Red de Facebook: Gephi


Red de imágenes de Facebook: Gephi

Visualizando la red con igraph

R siempre ha sido capaz de manejar la adición de imágenes a gráficos de red (y gráficos en general). Intenté un par de paquetes diferentes para hacer esto; ambos funcionan bien. Estoy más familiarizado con el igraph, lo que hace que sea más fácil modificarlo, pero qgraph tiene incorporada la opción de imágenes de nodo, por lo que es muy fácil obtener un mapa de red con fotos de nodos (ver la siguiente sección, solo se necesitan unas pocas líneas). de código).

Antes de hacer una visualización de igraph usando imágenes de nodo, podemos trazar el gráfico a la antigua usanza y ajustar el diseño hasta que se vea bien.
Plot the network with igraph (no images yet)
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
require("png")
require("jpeg")
require("igraph")
fb.net <- graph.adjacency(fb.net.mat)
# Add node degree, node colors based on gender, and
# edge colors based on the color of the source node.
my.friends$degree <- degree(fb.net)
my.friends$color <- "gray45"
my.friends$color[my.friends$gender=="female"] <- "lightpink3"
my.friends$color[my.friends$gender=="male"]   <- "lightblue"
fb.net.el$color <- my.friends$color[match(fb.net.el$Source, my.friends$name)]
l <- layout.fruchterman.reingold(fb.net, niter=10000,area=vcount(fb.net)^2.3,
                                  repulserad=vcount(fb.net)^2.2)
png("Facebook-friends-net-IGRAPH.png", width = 2500, height = 2000)
plot(fb.net, vertex.size=my.friends$degree/20, vertex.label=NA,
     vertex.color=my.friends$color, edge.color=fb.net.el$color,
     edge.width=1, edge.arrow.size=0, edge.curved=0.3,  layout=l)
dev.off()

Para trazar con imágenes, aplicaremos el diseño que creamos anteriormente y trazaremos el grafo, pero esta vez con cuadrados blancos para los nodos. Luego usaremos las coordenadas devueltas desde la función de diseño para superponer las fotos sobre esos cuadros blancos. Una cosa que tardó un poco en descubrirse (la obtuve gracias a un comentario dejado en algún lugar en las interwebs por el autor de qgraph Sacha Epskamp) es que el diseño debe ser re-escalado a [-1,1] primero.

Plot the image network with igraph
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# Rescale the layout so it goes from -1 to 1
l <- layout.norm(l, -1, 1, -1, 1)
  
png("Facebook-friends-net-IGRAPH.png", width = 2500, height = 2000)
plot(fb.net, vertex.size=4, vertex.label=NA, edge.color=fb.net.el$color,
     vertex.shape="square",vertex.color="white", vertex.frame.color="white",
     edge.width=1, edge.arrow.size=0, edge.curved=0.2,  layout=l)
img.sc <- 0.03 #Image scaling
for (i in 1:dim(l)[1]) {
  img <- my.friends$picture.dld[i]
  img <- if(grepl(".jpg", img)) readJPEG(img) else "gray20"
  rasterImage(img, l[i,1]-img.sc, l[i,2]-img.sc, l[i,1]+img.sc, l[i,2]+img.sc)
}
dev.off()
detach(package:igraph)

Y así es como se ven los archivos de imagen exportados:


Red de Facebook: igraph

Red de fotografías de Facebook: igraph


Visualizando la red con qgraph

Realmente no hay mucho que explicar aquí: las imágenes de nodo son una opción incorporada para qgraph. La función qgraph tomará una matriz y un vector de nombres de imágenes (con rutas), y producirá un gráfico con imágenes de nodo de inmediato sin ningún retoque adicional.
.
Plot the image network with qgraph
83
84
85
86
87
88
89
90
91
require("png")
require("qgraph")
png("Facebook-friends-net-2014-04-QGRAPH.png", width = 2500, height = 2000)
qgraph(fb.net.mat, images = my.friends$picture.dld, labels = F,
        borders = F, esize=0.1, curve=0.2, curveAll=T, edge.color="gray55")
dev.off()
detach(package:qgraph)



Red de Facebook: qgraph

[Actualización abril 26 2014] Esteban Moro me recordó que no hay necesidad de reescalar manualmente los diseños de igraph ahora - uno puede usar layout.norm () en su lugar (script actualizado en consecuencia).
Hugle en GitHub Gist señaló amablemente un par de errores tipográficos, que ahora están corregidos.