Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
#==========================================================#
# Visualizing Facebook networks with friend photos #
# Katya Ognyanova, www.kateto.net, @ognyanova #
#==========================================================#
# Find more details at http://bit.ly/fbgephi
#==========================================================#
#### Collect the data using the RFacebook package ####
install.packages("Rfacebook")
library(Rfacebook)
# To get authenticated, first register as a developer here:
# https://developers.facebook.com/apps and create a new app.
# Then replace "123456789" below with the actual info
# you'll find in the "Settings" panel of your app.
# You also need to set Settings -> Website -> Site URL
# there to be http://localhost:1410/
oauth <- fbOAuth(app_id = "123456789",
app_secret = "123456789",
extended_permissions = T)
save(oauth, file="fb_oauth")
# load(file="fb_oauth")
# Get friend info:
my.friends <- getFriends(oauth, simplify=F)
head(my.friends)
colnames(my.friends)
# Get friend network in two formats, matrix and edgelist:
fb.net.mat <- getNetwork(oauth, format = "adj.matrix")+0 # boolean, +0 to get numeric
fb.net.el <- as.data.frame(getNetwork(oauth, format = "edgelist"))
#==========================================================#
#### Download friend profile photos from Fb ####
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')
}
#==========================================================#
#### Save the data for import into Gephi ####
# Two files: an edgelist csv containing Source and Target columns,
# and a node attributes csv, containing IDs that match those in the
# Source/Target columns. To use the Gephi Image preview plugin,
# we also need a column called "image" and containing
# the file name of each picture.
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)
# Note that we could use other formats like gexf for the export/import,
# but in my experience for simple nets that just ends up being more work
# than going with the csv files.
#==========================================================#
#### Plot the network using the igraph package ####
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.65)
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()
# Now plot using images for the nodes:
# Rescale the layout so it goes from -1 to 1
l <- layout.norm(l, -1, 1, -1, 1)
png("Facebook-friends-net-IGRAPH-Photos.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:png)
detach(package:jpeg)
detach(package:igraph)
#==========================================================#
#### Plot the network using the qgraph package ####
require("png")
require("qgraph")
png("Facebook-friends-net-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:png)
detach(package:qgraph)
#==========================================================##
hugle commented Apr 21, 2014

Thank you very much for sharing,

Some typo here:

at line 79:
my.friend$image <- gsub("FBImages/(*.)", "\1", my.friends$picture.dld)
should be :
my.friends$image...

at line 130:
better add "jpeg" since you have applied "readJPEG" function

at line 143:
require("qraph")
should be:
require("qgraph")

Thanks again!:)

Owner
kateto commented Apr 26, 2014

Will fix the typos, thanks for letting me know!

Correct the FBImages directory names in loop

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment