Introdução geral à análise de redes sociais usando o R

Silvio Salej Higgins

Professor

Wellington Santos Souza

Monitor

🕷️🕸️ Roteiro da Apresentação

  • 🚀 Pacotes e Estruturas de Dados
    • Edgelist, Matriz de Adjacência e Grafo Simples
  • 📊 Visualização e Análise Básica
    • Plotagem: Básica e Personalizada
    • Funções: Vértices, Arestas, Conexões e Vizinhança
  • 🕸️ Propriedades e Descrição das estruturas relacionais
    • Análise de Propriedades da Rede
    • Subgrafos e Métricas de coesão e centralidade

🚀 Pacotes Necessários

Vamos começar instalando e carregando os pacotes que usaremos hoje.

# pacote para manipulação de dados
if(!require(tidyverse)) install.packages("tidyverse"); library(tidyverse)
# pacote para manipulação de redes sociais
if(!require(tidygraph)) install.packages("tidygraph"); library(tidygraph)
# pacote para visualização de redes sociais
if(!require(igraph)) install.packages("igraph"); library(igraph)
# pacote para visualização de redes sociais
if(!require(ggraph)) install.packages("ggraph"); library(ggraph)
# pacote para leitura de arquivos Excel
if(!require(readxl)) install.packages("readxl"); library(readxl)
# pacote para visualização de tabelas
if(!require(knitr)) install.packages("knitr"); library(knitr)
if(!require(kableExtra)) install.packages("kableExtra"); library(kableExtra)
# pacote para visualização de redes sociais
if(!require(networkD3)) install.packages("networkD3"); library(networkD3)
# pacote para estatísticas descritivas
if(!require(summarytools)) install.packages("summarytools"); library(summarytools)

1️⃣ Edgelist (Lista de Arestas)

Uma rede social (ou grafo) pode ser criada de várias formas no R.

A maneira mais comum é definir uma edgelist, ou seja, uma tabela com duas colunas onde cada linha representa uma interação (aresta) entre dois nós (vértices).

De Para
Nó A Nó B
Nó A Nó C

📥 Importando os Dados

📂 Arquivo Fonte

data for learning ucinet.xlsx: disponível na pasta de dados do UCINET

Famílias Florentinas do Século XV

Temos duas redes: uma de casamentos e outra de negócios.

📊 Estrutura dos Dados

🌐 A Rede (Estrutura das Conexões) 💼💍 Os Atributos (Tipos de Laços)
Mapeia quem se conecta com quem Classifica a natureza de cada laço usando colunas binárias (1 para Sim, 0 para Não)
From → To
  • PADGM: Laços de Casamento

  • PADGB: Laços de Negócios

👀 Espiando os Dados

Importando os dados de uma edgelist que contém as conexões entre as famílias florentinas.

  • 📂 definir o caminho do arquivo
  • 📂 definir a aba do arquivo
# Carregar os dados
df <- read_excel("~/UCINET data/data for learning ucinet.xlsx",
                         sheet = "families again")

📝 Estrutura dos Dados

FROM TO PADGM PADGB
ACCIAIUOLI MEDICI 1 0
ALBIZZI GINORI 1 0
ALBIZZI GUADAGNI 1 0
ALBIZZI MEDICI 1 0
BARBADORI CASTELLANI 1 1
BARBADORI MEDICI 1 1
BISCHERI GUADAGNI 1 1
BISCHERI PERUZZI 1 1

🧩 Criando o arquivo de Rede

Existe uma função no pacote igraph que facilita a criação de um grafo a partir de uma edgelist.

g <- graph_from_data_frame(d = df, directed = FALSE)

🏗️ Visualizando o objeto g

IGRAPH 3a8fe44 UN-- 15 54 -- 
+ attr: name (v/c), PADGM (e/n), PADGB (e/n)
+ edges from 3a8fe44 (vertex names):
 [1] ACCIAIUOLI--MEDICI       ALBIZZI   --GINORI       ALBIZZI   --GUADAGNI    
 [4] ALBIZZI   --MEDICI       BARBADORI --CASTELLANI   BARBADORI --MEDICI      
 [7] BISCHERI  --GUADAGNI     BISCHERI  --PERUZZI      BISCHERI  --STROZZI     
[10] BARBADORI --CASTELLANI   CASTELLANI--PERUZZI      CASTELLANI--STROZZI     
[13] ALBIZZI   --GINORI       ALBIZZI   --GUADAGNI     BISCHERI  --GUADAGNI    
[16] GUADAGNI  --LAMBERTESCHI GUADAGNI  --TORNABUONI   GUADAGNI  --LAMBERTESCHI
[19] ACCIAIUOLI--MEDICI       ALBIZZI   --MEDICI       BARBADORI --MEDICI      
[22] MEDICI    --RIDOLFI      MEDICI    --SALVIATI     MEDICI    --TORNABUONI  
+ ... omitted several edges

️🕷️ Visualizando a Rede

ggraph(g, layout = "kk") + # Usando o layout Kamada-Kaway
  geom_edge_link() + # Adiciona as arestas
  geom_node_point() + # Adiciona os nós
  theme_void() + # Remove o fundo
  labs(title = "Rede das Famílias Florentinas")

2️⃣ Matriz de Adjacência

Uma rede social também pode ser representada por uma matriz de adjacência, onde cada célula indica a presença ou ausência de uma conexão entre dois nós.

A matriz de adjacência é uma tabela onde as linhas e colunas representam os nós, e os valores indicam se há uma conexão entre eles (1) ou não (0).

Nó A Nó B Nó C
Nó A 0 1 1
Nó B 1 0 0
Nó C 1 0 0

📥 Importando a Matriz

📂 Arquivo Fonte

PADGETT_PADGM.csv: criei esse arquivo a partir do Ucinet. - Abra o Ucinet e carregue a rede. Vá para Matrix Editor > File > Open > Selecione o arquivo > Salve As > .csv.

# Carregar a matriz de adjacência
matriz_adj <- read.csv("~/UCINET data/PADGETT_PADGM.csv", sep = ",",
                       row.names = "id")
# 📝 Estrutura da Matriz de Adjacência
head(matriz_adj)[1:6] 
           ACCIAIUOLI ALBIZZI BARBADORI BISCHERI CASTELLANI GINORI
ACCIAIUOLI          0       0         0        0          0      0
ALBIZZI             0       0         0        0          0      1
BARBADORI           0       0         0        0          1      0
BISCHERI            0       0         0        0          0      0
CASTELLANI          0       0         1        0          0      0
GINORI              0       1         0        0          0      0

🧩 Criando o Grafo a partir da Matriz de Adjacência

# Transformar DF em matriz

matriz_adj <- as.matrix(matriz_adj)

# Criar o grafo a partir da matriz de adjacência

g_padgm <- graph.adjacency(matriz_adj,
                                       mode = "undirected",
                                       diag = F)

️🕷️ Visualizando a Rede

ggraph(g_padgm, layout = "fr") + # Usando o layout Fruchterman-Reingold
  geom_edge_link() + # Adiciona as arestas
  geom_node_point() + # Adiciona os nós
  theme_void() + # Remove o fundo
  labs(title = "Rede das Famílias Florentinas")

3️⃣ Criando um grafo rápido diretamente no R

# Criar um grafo simples

g_simple <- graph_from_literal(
  A -+ B, 
  B -+ C, 
  C +-+ D, 
  D -+ A,  
  E -+ A, 
  H -+ G, 
  A +-+ G 
)

️🕷️ Visualizando a Rede Simples

ggraph(g_simple, layout = "kk") + 
    geom_edge_fan(arrow = arrow(length = unit(2.5, 'mm'), angle = 15), 
    end_cap = circle(3, 'mm')) + 
    geom_node_point(size = 10, color = "skyblue") +
    geom_node_text(aes(label = name), repel = TRUE, size = 3.5, 
                   color = "black") + theme_void() 

️🕷️ Fluxo de dados UCINET > Pajek

Abra o Ucinet e siga os passos:

  • Vá para Data > Export > Pajek.

  • Escolha o tipo de arquivo: Network para a rede.

  • Salve o arquivo com a extensão .net.

️🕷️ Fluxo de dados Pajek > R

Abra o Pajek e siga os passos:

  • Vá para File > Network > Read.

  • Selecione o arquivo .net que você salvou.

  • Vá para Tools > R > Send to R > Current Network.

Aqui será gerado 2 códigos R: (I) PajekSource, pasta de localização do arquivo (II) PajekR que você pode rodar diretamente no RStudio.

🎨 Personalizando a Visualização da rede de Casamentos

# Converter para tidygraph para filtrar os laços de casamento
g_tidy <- as_tbl_graph(g)

padgm <- g_tidy  |> 
  activate(edges)  |> 
  filter(PADGM == 1) # Filtrar arestas de casamento

G1 = ggraph(padgm, layout = "kk") + 
 geom_edge_link(alpha = 0.5, color = "red") + 
 geom_node_point(color = "blue", alpha = 0.7, size = 3) + 
 geom_node_text(aes(label = name), 
                  repel = TRUE, size = 3) +
 theme_void() + 
 labs(title = "Rede de Casamentos das Famílias Florentinas")

🕷️ Visualizando a Rede

🎨 Personalizando a Visualização da rede de Negócios

G2 = g_tidy  |> 
 activate(edges)  |> 
 filter(PADGB == 1)  |>  # Filtrar arestas de Negócios
 ggraph(layout = "kk") + 
 geom_edge_link(alpha = 0.5, color = "red") + 
 geom_node_point(color = "blue", alpha = 0.7, size = 3) + 
 geom_node_text(aes(label = name), 
                  repel = TRUE, size = 3) +
  theme_void() + # Remove o fundo
  labs(title = "Rede de Negócios das Famílias Florentinas")

🕷️ Visualizando a Rede

🕷️ Visualizando a Rede usando o plot

plot(g)

🎨 Personalizando a Visualização usando o plot

plot(g_padgm,
     vertex.label.cex = 0.5, # Tamanho dos rótulos
     vertex.size = 20, # Tamanho dos nós
     vertex.color = "lightblue", # Cor dos nós
     edge.color = "gray", # Cor das arestas
     main = "Rede de Casamento das Famílias Florentinas") 

🕷️ Visualizando a Rede

🎨 Personalizando a Visualização usando o plot layout

# Ajustando o layout
g_padgm |>
 plot(vertex.label = NA, # Rótulos dos nós
     vertex.label.cex = 0.5, # Tamanho dos rótulos
     vertex.size = 10, # Tamanho dos nós
     vertex.color = "lightblue", # Cor dos nós
     edge.color = "gray", # Cor das arestas
     layout = layout_in_circle(g), # Layout ajustado
     main = "Rede de Casamento das Famílias Florentinas") # Título do gráfico

🕷️ Visualizando a Rede

📊 Análise Básica (1)

Arestas

# Exibe os primeiros 10 arestas
E(g_padgm)[1:10] 
+ 10/20 edges from 3ad06ea (vertex names):
 [1] ACCIAIUOLI--MEDICI     ALBIZZI   --GINORI     ALBIZZI   --GUADAGNI  
 [4] ALBIZZI   --MEDICI     BARBADORI --CASTELLANI BARBADORI --MEDICI    
 [7] BISCHERI  --GUADAGNI   BISCHERI  --PERUZZI    BISCHERI  --STROZZI   
[10] CASTELLANI--PERUZZI   

Vértices

# Vértices
# Exibe os primeiros 10 vértices
V(g_padgm)[1:10] 
+ 10/16 vertices, named, from 3ad06ea:
 [1] ACCIAIUOLI   ALBIZZI      BARBADORI    BISCHERI     CASTELLANI  
 [6] GINORI       GUADAGNI     LAMBERTESCHI MEDICI       PAZZI       

📊 Análise Básica (2)

Verifica se dois nós estão conectados

Caso verdadeiro, retorna TRUE; caso contrário, retorna FALSE.

are.connected(g_padgm, "ALBIZZI", "BARBADORI") 
[1] FALSE
are.connected(g_padgm, "ACCIAIUOLI", "MEDICI") 
[1] TRUE

📊 Análise Básica (3)

Analisa vizinhança de um vertice

# neighbors(g_padgm, "MEDICI")
adjacent_vertices(g_padgm, "MEDICI")
$MEDICI
+ 6/16 vertices, named, from 3ad06ea:
[1] ACCIAIUOLI ALBIZZI    BARBADORI  RIDOLFI    SALVIATI   TORNABUONI

Nós a uma distância n do vértice

# nós a duas arestas de distância do nó MEDICI
neighborhood(g_padgm, order = 2, "MEDICI")
[[1]]
+ 12/16 vertices, named, from 3ad06ea:
 [1] MEDICI     ACCIAIUOLI ALBIZZI    BARBADORI  RIDOLFI    SALVIATI  
 [7] TORNABUONI GINORI     GUADAGNI   CASTELLANI STROZZI    PAZZI     

📊 Funções Básicas (4)

# subgrafo
sub <- subgraph.edges(g, E(g)[.inc("MEDICI")])
plot(sub)

🕸️ Análise de Propriedades da Rede

📊 Propriedades Básicas (1)

  • Direção
is.directed(g_padgm)
[1] FALSE
  • Número de Nós (Vértices)
vcount(g_padgm)
[1] 16

📊 Propriedades Básicas (2)

  • Número de Arestas
ecount(g_padgm)
[1] 20
  • Tipo de de grafo
is.weighted(g_padgm)
[1] FALSE

📊 Descrição das estruturas relacionais (Coesão (1))

  • Densidade
graph.density(g_padgm)
[1] 0.1666667
# em porcentagem
round(graph.density(g_padgm) * 100,2)
[1] 16.67
  • Distância média entre dois nós
mean_distance(g_padgm, directed = FALSE)
[1] 2.485714

📊 Descrição das estruturas relacionais (Coesão (2))

  • Frequências das distâncias
distances <- distances(g_padgm)
table(distances)
distances
  0   1   2   3   4   5 Inf 
 16  40  70  64  30   6  30 

📊 Descrição das estruturas relacionais (Coesão (3))

  • Diâmetro
diameter(g_padgm)
[1] 5
  • número de componentes
components(g_padgm)$no
[1] 2

📊 Descrição das estruturas relacionais (Centralidade (1))

  • Grau absoluto
degree(g_padgm, mode = "all") |> 
  as.data.frame() |> 
  rename(degree = `degree(g_padgm, mode = "all")`) |> 
  arrange(desc(degree)) |> 
  head(5) 
         degree
MEDICI        6
GUADAGNI      4
STROZZI       4
ALBIZZI       3
BISCHERI      3

🕸️ Plotando a Centralidade de Grau

G3=ggraph(g_padgm, layout = "fr") + 
  geom_edge_link() + 
  geom_node_point(aes(size = degree(g_padgm, mode = "all")), 
                  color = "blue") + 
  geom_node_text(aes(label = name), repel = TRUE, size = 3, color = "red") + 
  theme_void() + 
  labs(title = "Centralidade de Grau das Famílias Florentinas")+
  scale_size_continuous(range = c(1, 15)) + # Ajusta o tamanho dos nós
  theme(legend.position = "none") # Remove a legenda

🕸️ Plotando a Centralidade de Grau

📊 Descrição das estruturas relacionais (Centralidade (2))

  • Proximidade
closeness(g_padgm, mode = "all") |> 
  as.data.frame() |> 
  rename(closeness = `closeness(g_padgm, mode = "all")`) |> 
  arrange(desc(closeness)) |> 
  head(5)
            closeness
MEDICI     0.04000000
RIDOLFI    0.03571429
ALBIZZI    0.03448276
TORNABUONI 0.03448276
GUADAGNI   0.03333333

🕸️ Plotando a Centralidade de Proximidade

G4=ggraph(g_padgm, layout = "fr") + 
  geom_edge_link() + 
  geom_node_point(aes(size = closeness(g_padgm, mode = "all")), 
                  color = "blue") + 
  geom_node_text(aes(label = name), repel = TRUE, size = 3) + 
  theme_void() + 
  labs(title = "Centralidade de Proximidade das Famílias Florentinas")+
  scale_size_continuous(range = c(1, 15)) + # Ajusta o tamanho dos nós
  theme(legend.position = "none") # Remove a legenda

🕸️ Plotando a Centralidade de Proximidade

📊 Descrição das estruturas relacionais (Centralidade (3))

  • Intermediação
betweenness(g_padgm, directed = FALSE) |> 
  as.data.frame() |> 
  rename(betweenness = `betweenness(g_padgm, directed = FALSE)`) |> 
  arrange(desc(betweenness)) |> 
  head(5)
         betweenness
MEDICI      47.50000
GUADAGNI    23.16667
ALBIZZI     19.33333
SALVIATI    13.00000
RIDOLFI     10.33333

🕸️ Plotando a Centralidade de Intermediação

G5=ggraph(g_padgm, layout = "circle") + 
  geom_edge_link() + 
  geom_node_point(aes(size = betweenness(g_padgm, directed = FALSE)), 
                  color = "blue") + 
  geom_node_text(aes(label = name), repel = TRUE, size = 3) + 
  theme_void() + 
  labs(title = "Centralidade de Intermediação das Famílias Florentinas")+
  scale_size_continuous(range = c(1, 10)) + # Ajusta o tamanho dos nós
  theme(legend.position = "none") # Remove a legenda

🕸️ Plotando a Centralidade de Intermediação

📊 Descrição das estruturas relacionais (Centralidade (4))

  • Centralidade de Autovetor (Eigenvector)
eigen_centrality(g_padgm)$vector |> 
  as.data.frame() |> 
  rename(eigen_centrality = `eigen_centrality(g_padgm)$vector`) |> 
  arrange(desc(eigen_centrality)) |> 
  head(5)
           eigen_centrality
MEDICI            1.0000000
STROZZI           0.8272688
RIDOLFI           0.7937398
TORNABUONI        0.7572302
GUADAGNI          0.6718805

🕸️ Plotando a Centralidade de Autovetor

G6=ggraph(g_padgm, layout = "fr") + 
  geom_edge_link() + 
  geom_node_point(aes(size = eigen_centrality(g_padgm)$vector), 
                  color = "blue") + 
  geom_node_text(aes(label = name), repel = TRUE, size = 3) + 
  theme_void() + 
  labs(title = "Centralidade de Autovetor das Famílias Florentinas")+
  scale_size_continuous(range = c(1, 15)) + # Ajusta o tamanho dos nós
  theme(legend.position = "none") # Remove a legenda

🕸️ Plotando a Centralidade de Autovetor

📊 Descrição das estruturas relacionais (Centralidade (5))

  • Prestígio de Proximidade (Reach Centrality)
power_centrality(g_padgm, exponent = 0.5) |> 
  as.data.frame() |> 
  rename(power_centrality = `power_centrality(g_padgm, exponent = 0.5)`) |> 
  arrange(desc(power_centrality)) |> 
  head(5)
             power_centrality
PUCCI              0.00000000
PAZZI             -0.05398386
GINORI            -0.20393902
LAMBERTESCHI      -0.22493275
SALVIATI          -0.53941015

🕸️ Plotando o Prestígio de Proximidade

G7=ggraph(g_padgm, layout = "fr") + 
  geom_edge_link() + 
  geom_node_point(aes(size = power_centrality(g_padgm, exponent = 0.5)), 
                  color = "blue") + 
  geom_node_text(aes(label = name), repel = TRUE, size = 3) + 
  theme_void() + 
  labs(title = "Prestígio de Proximidade das Famílias Florentinas")+
  scale_size_continuous(range = c(1, 10)) + # Ajusta o tamanho dos nós
  theme(legend.position = "none") # Remove a legenda

🕸️ Plotando o Prestígio de Proximidade

📝 Tabela com as métricas

tab=data.frame(Métrica = c("Número de nós",
                       "Número de relacões",
                       "Número de componentes",
                       "Densidade",
                       "Distancia geodésica média",
                       "Diâmetro"
),Valor = c(round(gorder(g_padgm),0),
          round(gsize(g_padgm),0),
          round(components(g_padgm)$no,2),
          round(edge_density(g_padgm),2),
          round(mean_distance(g_padgm),0),
          round(diameter(g_padgm),0)
)
) |> 
  kableExtra::kbl(caption = "Métricas da Rede") |> 
  kableExtra::kable_classic(full_width = T, html_font = "Cambria") 

🪟️ Visualizando a Tabela

Métricas da Rede
Métrica Valor
Número de nós 16.00
Número de relacões 20.00
Número de componentes 2.00
Densidade 0.17
Distancia geodésica média 2.00
Diâmetro 5.00

📝 Estatísticas Descritivas das Métricas

nos <- as.data.frame(V(g_padgm))

# Centralidade de grau
nos$grau <- degree(g_padgm)

# grau de intermediação
nos$intermediacao <- round(betweenness(g_padgm),2)

# grau de proximidade
nos$proximidade <- round(closeness(g_padgm, normalized = TRUE)
, 2)
# Centralidade de autovetor
nos$autovetor <- eigen_centrality(g_padgm)$vector

🪟️ Visualizando as Estatísticas Descritivas

Estatísticas Descritivas das Métricas
Mean Std.Dev Min Median Max N.Valid N Pct.Valid
autovetor 0.51 0.29 0.00 0.58 1.00 16 16 100.00
grau 2.50 1.51 0.00 3.00 6.00 16 16 100.00
intermediacao 9.75 12.30 0.00 8.41 47.50 16 16 100.00
proximidade 0.42 0.07 0.29 0.40 0.56 15 16 93.75

📝 Referências

R igraph manual pages

Network Analysis and Visualization with R and igraph

Quantitative Social Science - KOSUKE IMAI

Network graph

️🕷️🚀😍😁🤗🤓🙏 Obrigado pela atenção! 🕸️🕷️🚀😍😁🤗🤓🙏