Mostrando entradas con la etiqueta centralidad de grado. Mostrar todas las entradas
Mostrando entradas con la etiqueta centralidad de grado. Mostrar todas las entradas

lunes, 9 de diciembre de 2019

Centralidad de grado y variación en los pesos de los enlaces

Centralidad de grado y variación en los pesos de los enlaces

Tore Opsahl




La centralidad de los nodos, o la detección e identificación de los nodos centrales en una red, ha sido un tema clave en los estudios de redes. La medida básica de centralidad del nodo es el grado, que se define como el número de conexiones o vínculos que tiene un nodo focal (Freeman, 1978). El grado es un indicador básico y a menudo se usa como primer paso cuando se estudian redes (Wasserman y Faust, 1994). Para describir formalmente esta medida y facilitar la comparación entre las diferentes medidas introducidas en esta publicación, esta medida se puede formalizar para un nodo focal i como:

donde j representa todos los demás nodos, N es el número total de nodos, y x es la matriz de adyacencia, en la que la celda se define como 1 si el nodo i está conectado al nodo j, y 0 en caso contrario.

El grado generalmente se ha extendido a la suma de pesos cuando se analizan redes ponderadas y la fuerza del nodo etiquetado (Barrat et al., 2004). Esta medida se puede formalizar de la siguiente manera:

donde w es la matriz de adyacencia ponderada, en la que es mayor que 0 si el nodo i está conectado al nodo j, y el valor representa el peso del lazo. Esto es igual a la definición de grado si la red es binaria, es decir, cada vínculo tiene un peso de 1. Por el contrario, en redes ponderadas, los resultados de estas dos medidas son diferentes. Dado que la fuerza del nodo tiene en cuenta los pesos de los lazos, esta ha sido la medida preferida para analizar redes ponderadas (por ejemplo, Barrat et al., 2004; Opsahl et al., 2008).





Grado y fortaleza: dos nodos con la misma fuerza de nodo, pero diferente número de enlaces.


Sin embargo, la fuerza del nodo es una medida contundente, ya que solo tiene en cuenta el nivel total de participación de un nodo en la red, y no el número de otros nodos a los que se conectó. Para ejemplificar esto, el nodo A y el nodo B tienen la misma fuerza, pero el nodo A está conectado a tres veces más nodos que el nodo A y, por lo tanto, está involucrado en más partes de la red. Como el grado y la fuerza pueden ser indicadores del nivel de participación de un nodo en la red circundante, Opsahl et al propusieron una segunda generalización. (2010) que incorporaron tanto el número de empates como la suma de los pesos de empate. Su medida puede formalizarse como:
donde es un parámetro de ajuste positivo que controla la importancia relativa del número de lazos y la suma de los lazos. Específicamente, hay dos valores de referencia (0 y 1), y si el parámetro se establece en cualquiera de estos valores, se reproduce la medida existente. Si el parámetro se establece en el valor de referencia de 0, los resultados de la medida se basan únicamente en el número de vínculos, y son iguales a los encontrados al aplicar la medida de Freeman (1978) a una versión binaria de una red donde todos los lazos con un peso mayor que 0 están configurados para presentar. Por el contrario, si el valor del parámetro es 1, los resultados de la medida se basan solo en ponderaciones de enlaces y son idénticos a la generalización de grado ya propuesta (Barrat et al., 2004). Para otros valores de , se obtienen resultados alternativos, que se basan tanto en el número de lazos como en los pesos de los lazos. En particular, se pueden distinguir dos rangos de valores. Primero, un conjunto de parámetros entre 0 y 1 valoraría positivamente tanto el número de enlaces  como los ponderadores de enlace. Esto implica que ambos incrementos en el grado y la fuerza del nodo aumentarán el resultado. En segundo lugar, si el valor del parámetro está por encima de 1, las medidas valorarían positivamente la resistencia del enlace y negativamente el número de lazos. Los nodos con un promedio de lazos más fuertes obtendrán una puntuación más alta.


Variación en los pesos de lazos: dos nodos con los mismos puntajes utilizando las medidas de grado de Freeman (1978), Barrat et al. (2004) y Opsahl et al. (2010).

Todas las medidas anteriores son insensibles a la variación en los pesos de corbata. Por ejemplo, los dos nodos, A y B, en este diagrama tienen el mismo número de conexiones, la misma fuerza de nodo y logran el mismo puntaje usando la segunda generalización, ya que es un producto del grado y la fuerza de nodo. Mientras que las medidas de cercanía e intermediación propuestas en Opsahl et al. (2010) son sensibles a la variación en los pesos de lazos, la medida del grado fue diseñada para no ser. Sin embargo, una medida estrechamente relacionada con las medidas de cercanía y entremedio que es sensible a las diferencias de peso puede definirse de la siguiente manera:

Al exponer el peso de la corbata en lugar del peso promedio de la corbata, la medida se vuelve sensible a la variación en los pesos de la corbata. Por ejemplo, el nodo A y el nodo B obtendrían el siguiente puntaje utilizando las diversas medidas:
Medida Nodo
A B
Freeman’s 2 2
Barrat et al.’s 4 4
Opsahl et al.’s, alpha=0.5 2.83 2.83
Opsahl et al.’s, alpha=1.5 5.66 5.66
New measure, alpha=0.5 2.83 2.73
New measure, alpha=1.5 5.66 6.20

Como se puede ver en la tabla anterior, la nueva medida está estrechamente vinculada a la generalización propuesta por Opsahl et al. (2010); sin embargo, cuando los pesos de lazos son diferentes, la medida varía entre los dos nodos. Del mismo modo que las otras medidas de centralidad que utilizan un parámetro de ajuste, el parámetro de ajuste en estas medidas controla la importancia relativa del número de lazos y la suma de los lazos. Además, también controla si la variación en los pesos de lazo debe descontarse o considerarse favorable. Un parámetro entre 0 y 1 descuentos, mientras que un parámetro superior a 1, aumenta el resultado de la medida cuando los pesos de lazo son diferentes.

¿Quiere probarlo con tus datos?

A continuación se muestra el código para calcular la medida de grado propuesta. Debe tener el paquete tnet instalado antes de ejecutar el código.

.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# Load tnet
library(tnet)
# Load a function to calculate the new measures
degree2_w <- function (net, type="out", alpha = 1) {
    net <- as.tnet(net, type="weighted one-mode tnet")
    if (type == "in") {
        net <- data.frame(i = net[, 2], j = net[, 1], w = net[,3])
        net <- net[order(net[, "i"], net[, "j"]), ]
    }
    index <- cumsum(!duplicated(net[, 1]))
    k.list <- cbind(unique(net[, 1]), NaN, NaN, NaN)
    dimnames(k.list)[[2]] <- c("node", "degree", "output", "alpha")
    k.list[, "degree"] <- tapply(net[, "w"], index, length)
    k.list[, "output"] <- tapply(net[, "w"], index, sum)
    net[,"w"] <- net[,"w"]^alpha
    k.list[, "alpha"] <- tapply(net[, "w"], index, sum)
    if (max(net[, c("i", "j")]) != nrow(k.list)) {
        k.list <- rbind(k.list, cbind(1:max(net[, c("i", "j")]), 0, 0, 0))
        k.list <- k.list[order(k.list[, "node"]), ]
        k.list <- k.list[!duplicated(k.list[, "node"]), ]
    }
    return(k.list)
}
# Load a sample network
net <- cbind(
i=c(1,1,2,2),
j=c(2,3,1,3),
w=c(2,2,1,3))
# Calculate the measures
degree_w(net, measure=c("degree","output","alpha"), alpha=1.5)
degree_w(net, measure=c("degree","output","alpha"), alpha=0.5)
degree2_w(net, alpha=0.5)
degree2_w(net, alpha=1.5)

Referencias


Barrat, A., Barthelemy, M., Pastor-Satorras, R., Vespignani, A., 2004. The architecture of complex weighted networks. Proceedings of the National Academy of Sciences 101 (11), 3747-3752.

Freeman, L. C., 1978. Centrality in social networks: Conceptual clarification. Social Networks 1, 215-239.

Opsahl, T., Agneessens, F., Skvoretz, J. (2010). Node centrality in weighted networks: Generalizing degree and shortest paths. Social Networks 32, 245-251.

Opsahl, T., Colizza, V., Panzarasa, P., Ramasco, J. J., 2008. Prominence and control: The weighted rich-club effect. Physical Review Letters 101 (168702).

Wasserman, S., Faust, K., 1994. Social Network Analysis: Methods and Applications. Cambridge University Press, New York, NY.

viernes, 8 de febrero de 2019

Redes de coautorías de economistas argentinos en un congreso principal

Redes de coautorías de economistas argentinos

Author(s):
Juan M.C. Larrosa , (Universidad Nacional del Sur, Bahia Blanca, Argentina and Instituto de Investigaciones Económicas y Sociales del Sur (IIESS), Altos de Palihue Bahia Blanca, Argentina)


Propósito

Este documento tiene como objetivo proporcionar información sobre la estructura del trabajo colaborativo entre las economías argentinas. El estudio proporciona investigación aplicada específica de análisis de redes sociales centrada en esta profesión en este país específico.

Diseño / metodología / enfoque

La contribución optó por aplicar herramientas de análisis de redes sociales a los documentos presentados en un congreso y publicados en sus actas. Los autores se centran en la detección de actores principales, grupos de coautoría, profesionales que actúan como puentes entre grupos y diferencias entre los géneros.


Recomendaciones

El documento proporciona información empírica sobre cómo ha evolucionado la coautoría entre los economistas argentinos. Los autores encuentran que las propiedades estructurales de la red, los principales actores, tanto hombres como mujeres, las principales universidades o el centro que los afilia, una brecha de género que podría estar cerrando.

Limitaciones / implicaciones de la investigación

El documento se centra en la red para el período 1964-2014 sin una dinámica más detallada. Tampoco explica los principales temas trabajados por los autores.


Implicaciones prácticas

El trabajo proporciona conocimiento sobre cómo se crean los grupos en Economía en Argentina, cómo ha evolucionado la cooperación y cuál ha sido el papel de las mujeres en este desarrollo. También muestra cómo diferentes departamentos y entidades colaboran con éxito diverso en la creación de nuevos conocimientos en Economía en Argentina.

Originalidad / valor

El documento trabaja con datos de una fuente de información no estudiada anteriormente y contribuye a explicar un tipo particular de trabajo colaborativo en una profesión en Argentina.



Juan M.C. Larrosa, (2019) "Coauthorship networks of Argentine economists", Journal of Economics, Finance and Administrative Science, https://doi.org/10.1108/JEFAS-06-2018-0062


jueves, 31 de enero de 2019

Redes familiares y desempeño en el Cabildo de Buenos Aires

Political Power from Elite Family Networks in Colonial Buenos Aires


del Valle L.C., Larrosa J.M.C. (2019) Political Power from Elite Family Networks in Colonial Buenos Aires. In: Diebolt C., Rijpma A., Carmichael S., Dilli S., Störmer C. (eds) Cliometrics of the Family. Studies in Economic History. Springer, Cham


miércoles, 17 de octubre de 2018

Capital social como estructura social de la corrupción

El capital social predice el riesgo de corrupción en las ciudades 

Johannes Wachs, Taha Yasseri, Balázs Lengyel, János Kertész





La corrupción es una plaga social: las ganancias se acumulan en grupos pequeños, mientras que sus costos son asumidos por todos. Una variación significativa en su nivel entre y dentro de los países sugiere una relación entre la estructura social y la prevalencia de la corrupción, sin embargo, faltan estudios empíricos a gran escala debido a la falta de datos. En este documento relacionamos las características estructurales del capital social de las ciudades con la corrupción en sus gobiernos locales. Al usar conjuntos de datos de Hungría, cuantificamos el riesgo de corrupción mediante la supresión de la competencia y la falta de transparencia en los contratos públicos adjudicados de la ciudad. Caracterizamos el capital social utilizando datos de redes sociales de una plataforma en línea popular. Al controlar los factores sociales, económicos y políticos, encontramos que los asentamientos con redes sociales fragmentadas, que indican un exceso de bonding social capital tienen un mayor riesgo de corrupción y las ciudades con conectividad externa más diversa, lo que sugiere un excedente de bridging social capital está menos expuesto a la corrupción. Interpretamos que la fragmentación fomenta el favoritismo y la conformidad en el grupo, lo que aumenta la corrupción, mientras que la diversidad facilita la imparcialidad en la vida pública y reprime la corrupción.

Cite as: arXiv:1810.05485 [cs.SI]
  (or arXiv:1810.05485v1 [cs.SI] for this version)


viernes, 22 de junio de 2018

Centralidad en redes ponderadas

Centralidad de nodo en redes ponderadas

Tore Opsahl


La centralidad de los nodos, o la identificación de qué nodos son más "centrales" que otros, ha sido un tema clave en el análisis de redes (Freeman, 1978; Bonacich, 1987; Borgatti, 2005; Borgatti et al., 2006). Freeman (1978) argumentó que los nodos centrales eran aquellos "en el meollo de las cosas" o puntos focales. Para ejemplificar su idea, utilizó una red que consta de 5 nodos. El nodo medio tiene tres ventajas sobre los otros nodos: tiene más vínculos, puede alcanzar a todos los demás más rápidamente y controla el flujo entre los demás. Con base en estas tres características, Freeman (1978) formalizó tres medidas diferentes de la centralidad del nodo: grado, cercanía e interdependencia. Grado es la cantidad de nodos a los que está conectado un nodo focal y mide la participación del nodo en la red. Su simplicidad es una ventaja: solo debe conocerse la estructura local alrededor de un nodo para que se calcule (p. Ej., Cuando se utilizan datos de la Encuesta social general, McPherson et al., 2001). Sin embargo, existen limitaciones: la medida no toma en consideración la estructura global de la red. Por ejemplo, aunque un nodo podría estar conectado a muchos otros, podría no estar en condiciones de alcanzar a otros rápidamente para acceder a los recursos, como la información o el conocimiento (Borgatti, 2005; Brass, 1984). Para capturar esta característica, la centralidad de cercanía se definió como la suma inversa de las distancias más cortas a todos los demás nodos desde un nodo focal. Una de las principales limitaciones de la cercanía es la falta de aplicabilidad a las redes con componentes desconectados (consulte Centralidad de proximidad en redes con componentes desconectados). La última de las tres medidas, betweenness, evalúa el grado en que un nodo se encuentra en la ruta más corta entre otros dos nodos y puede canalizar el flujo en la red. Al hacerlo, un nodo puede ejercer control sobre el flujo. Si bien esta medida tiene en cuenta la estructura de red global y puede aplicarse a redes con componentes desconectados, no deja de tener sus limitaciones. Por ejemplo, una gran proporción de nodos en una red generalmente no se encuentra en la ruta más corta entre ninguno de los otros dos nodos, y por lo tanto recibe la misma puntuación de 0.

 
Una red de estrella con 5 nodos y 4 enlaces. El tamaño de los nodos corresponde al grado de los nodos. Adaptado de Freeman (1978) y Opsahl et al. (2010).



Las tres medidas se han generalizado a redes ponderadas. En un primer conjunto de generalizaciones, Barrat et al. (2004) grado generalizado tomando la suma de pesos en lugar de los nudos, mientras que Newman (2001) y Brandes (2001) utilizaron el algoritmo de Dijkstra (1959) de caminos más cortos para generalizar la cercanía y la interdependencia a redes ponderadas, respetuosamente (ver Rutas más cortas en Weighted Networks para más detalles). Estas generalizaciones se centraron únicamente en los pesos vinculados e ignoraron la característica original de las medidas: el número de vínculos. Como tal, un segundo conjunto de generalización fue propuesto por Opsahl et al. (2010) que incorpora tanto el número de vínculos como los pesos de enlace utilizando un parámetro de ajuste.

Grado

El grado es la más simple de las medidas de centralidad del nodo al usar la estructura local solo alrededor de los nodos. En una red binaria, el grado es el número de vínculos que tiene un nodo. En una red dirigida, un nodo puede tener un número diferente de enlaces salientes y entrantes, y por lo tanto, el grado se divide en grado y grado, respectivamente.

Por lo general, el grado se ha extendido a la suma de ponderaciones cuando se analizan las redes ponderadas (Barrat et al., 2004; Newman, 2004; Opsahl et al., 2008) y la resistencia del nodo etiquetada. Es igual a la definición tradicional de grado si la red es binaria (es decir, cada vínculo tiene un peso de 1). Por el contrario, en las redes ponderadas, los resultados de estas dos medidas son diferentes. Como la fuerza del nodo toma en consideración el peso de los enlaces, esta ha sido la medida preferida para analizar las redes ponderadas (por ejemplo, Barrat et al., 2004; Opsahl et al., 2008). Sin embargo, la fortaleza del nodo es una medida contundente, ya que solo toma en consideración el nivel total de participación de un nodo en la red, y no toma en cuenta la característica principal de las medidas originales formalizadas por Freeman (1978): el número de vínculos. Esta limitación se destaca por la centralidad de grado de las tres redes de ego de la tercera red EIES de Freeman. Los tres nodos han enviado aproximadamente la misma cantidad de mensajes; sin embargo, a un número bastante diferente de otros. Si se aplicó la medida original de Freeman (1978), el puntaje de centralidad del nodo en el panel A es casi cinco veces más alto que el nodo en el panel C. Sin embargo, al usar la generalización de Barrat et al., Obtienen aproximadamente el mismo puntaje.




Redes Ego de Phipps Arabie (A), John Boyd (B) y Maureen Hallinan (C) de la tercera red EIES de Freeman. El ancho de un enlace corresponde a la cantidad de mensajes enviados desde el nodo focal a sus contactos. Adoptado de Opsahl et al. (2010).


En un intento de combinar el grado y la fuerza, Opsahl et al. (2010) utilizó un parámetro de ajuste para establecer la importancia relativa de la cantidad de vínculos en comparación con los pesos de enlace. Específicamente, la medida de centralidad de grado propuesta fue el producto de la cantidad de nodos a los que está conectado un nodo focal y el peso promedio de estos nodos ajustado por el parámetro de ajuste. Hay dos valores de referencia para el parámetro de ajuste (0 y 1), y si el parámetro se establece en cualquiera de estos valores, se reproducen las medidas existentes (Barrat et al., 2004; Freeman, 1978). Si el parámetro se establece en el valor de referencia de 0, los resultados de las medidas se basan únicamente en el número de vínculos, y son iguales a la encontrada al aplicar la medida de Freeman (1978) a una versión binaria de una red donde todas las los lazos con un peso mayor a 0 se configuran como presentes. Al hacerlo, los pesos vinculados son completamente ignorados. Por el contrario, si el valor del parámetro es 1, la medida se basa solamente en los pesos de empate y es idéntica a la generalización ya propuesta (Barrat et al., 2004). Esto implica que no se tiene en cuenta el número de vínculos. La siguiente tabla destaca las diferencias entre las medidas de grado.
.
Nodo Grado medido por
Freeman (1978) Barrat et al. (2004) Opsahl et al. (2010; alpha=0.5) Opsahl et al. (2010; alpha=1.5)
Phipps Arabie (A) 28 155 66 365
John Boyd (B) 11 188 45 777
Maureen Hallinan (C) 6 227 37 1396

Para calcular las puntuaciones de grado de los nodos, a continuación se muestra un código de muestra para calcular los puntajes de grado de las neuronas del gusano c.elegans (Watts y Strogatz, 1998) utilizando el R-package tnet.
1
2
3
4
5
6
7
8
9
10
11
# Load tnet
library(tnet)
# Load the neural network of the c.elegans network
data(tnet)
# Calculate the out-degree of neurons and the generalised measures (alpha=0.5)
degree_w(net=celegans.n306.net, measure=c("degree","output","alpha"), alpha=0.5)
# Calculate the in-degree of neurons and the generalised measures (alpha=0.5)
degree_w(net=celegans.n306.net, measure=c("degree","output","alpha"), alpha=0.5, type="in")


Cercanía



La cercanía se define como la inversa de la lejanía, que a su vez es la suma de las distancias a todos los demás nodos (Freeman, 1978). La intención detrás de esta medida fue identificar los nodos que podrían llegar a otros rápidamente. Una limitación principal de la cercanía es la falta de aplicabilidad a redes con componentes desconectados: dos nodos que pertenecen a diferentes componentes no tienen una distancia finita entre ellos. Por lo tanto, la cercanía generalmente está restringida a los nodos dentro del componente más grande de una red. La publicación de blog Closeness Centrality in Networks with Disconnected Components sugiere un método para superar esta limitación,

La cercanía se ha generalizado a las redes ponderadas por Newman (2001), que utilizó el algoritmo de Dijkstra (1959) (para obtener más detalles, consulte Trayectos más cortos en Redes ponderadas). Para reiterar rápidamente el trabajo de Dijkstra (1959) y de Newman (2001) aquí:
  1. Dijkstra (1959) propuso un algoritmo para encontrar las rutas más cortas en una red donde los pesos podrían considerarse costos. La ruta menos costosa que conecta dos nodos fue la ruta más corta entre ellos (por ejemplo, una red de carreteras donde cada tramo de carretera tiene un costo de tiempo asignado).
  2. Newman (2001) transformó los pesos positivos en una red de colaboración en costos invirtiéndolos (dividiendo 1 por el peso).
  3. Sobre la base de los pesos invertidos, Newman (2001) aplicó el algoritmo de Dijkstra y encontró los caminos menos costosos entre todos los nodos.
  4. El costo total de las rutas de un nodo a todos los demás fue una medida de lejanía: cuanto mayor es el número, más cuesta que un nodo llegue a todos los otros nodos. Para crear una medida de proximidad, Newman (2001) siguió a Freeman (1978) e invirtió los números (1 dividido por la lejanía). Por lo tanto, una alta lejanía se transformó en una baja cercanía, y una baja lentitud se transformó en una gran cercanía.

De forma similar a la generalización de grado de Barrat et al. (2004), el algoritmo generalizado de Newman (2001) se centra únicamente en la suma de ponderaciones de relación y no tiene en cuenta la cantidad de vínculos en las rutas. Opsahl et al. (2010) la generalización de las rutas más cortas se puede aplicar para determinar la longitud de ellas.

Para calcular las puntuaciones de cercanía de los nodos, a continuación se muestra un código de muestra para calcular los puntajes de cercanía de las neuronas del gusano c.elegans (Watts y Strogatz, 1998) utilizando el paquete de R tnet.




.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Load tnet
library(tnet)
# Load the neural network of the c.elegans network
data(tnet)
# Calculate the binary closeness scores
closeness_w(net=celegans.n306.net, alpha=0)
# Calculate the first generation weighted closeness scores
closeness_w(net=celegans.n306.net, alpha=1)
# Calculate the second generation weighted closeness scores (alpha=0.5)
closeness_w(net=celegans.n306.net, alpha=0.5)

Intermediación

La medida en que un nodo forma parte de las transacciones entre otros nodos se puede estudiar utilizando la medida de interdependencia de Freeman (1978). En la red de muestra de la derecha, si los enlaces no tenían un peso asignado, las líneas grises intermitentes representan las 9 rutas más cortas de la red que pasan por nodos intermedios. El nodo resaltado es un intermedio en 8 de estas rutas. Esto le dará a este nodo una puntuación de interinidad de 8.



Brandes (2001) propuso un nuevo algoritmo para calcular la interrelación más rápido. Además de reducir el tiempo, este algoritmo también relajó la suposición de que los vínculos debían estar presentes o ausentes (es decir, una red binaria) y permitió que se calculase la interdependencia en redes ponderadas (tenga en cuenta que esta generalización es independiente de la medida de flujo propuesta por Freeman et al., 1991, que podría ser más apropiado en ciertos entornos). Esta generalización tiene en cuenta que, en las redes ponderadas, la transacción entre dos nodos podría ser más rápida a lo largo de las rutas con más nodos intermedios que están fuertemente conectados que las rutas con menos nodos intermedios débilmente conectados. Esto se debe al hecho de que los nodos intermedios fuertemente conectados tienen, por ejemplo, un contacto más frecuente que los conectados débilmente. Por ejemplo, el vínculo entre el nodo superior izquierdo y el nodo focal en la red de muestra anterior tiene cuatro veces la fuerza del enlace entre el nodo inferior izquierdo y el nodo focal. Esto podría significar que el nodo superior izquierdo tiene contacto más frecuente con el nodo focal que el nodo inferior izquierdo. A su vez, esto podría implicar que el nodo superior izquierdo podría dar al nodo focal una información (o una enfermedad) cuatro veces más rápido que el nodo inferior izquierdo. Si estamos estudiando los nodos que con mayor probabilidad canalizan información o enfermedades en una red, entonces la velocidad a la que viaja y las rutas que lleva se ven claramente afectadas por los pesos. La identificación de las rutas más cortas en redes ponderadas también se puede utilizar al identificar los nodos que canalizan transacciones entre otros nodos en redes ponderadas. Si suponemos que las transacciones en una red ponderada siguen las rutas más cortas identificadas por el algoritmo de Dijkstra en lugar de la que tiene el menor número de nodos intermedios, entonces el número de rutas más cortas que pasan por un nodo podría cambiar.

.
Nodo Medida de intermediación de
Freeman (1978) Brandes (2001) Opsahl et al. (2010; alpha=0.5)
1 0 4 0
2 8 8 8
3 0 0 0
4 0 0 0
5 4 4 4
6 0 0 0


Ahora, el nodo 1 (A) también obtuvo una puntuación de interdependencia de 4. Esto se debe a que se usa la ruta indirecta desde el nodo B al nodo C hasta A en lugar de la conexión directa.

De forma similar a la generalización de proximidad de Newman (2001), el algoritmo generalizado de Brandes (2001) se centra únicamente en la suma de ponderaciones de relación y no tiene en cuenta la cantidad de vínculos en las rutas. Opsahl et al. (2010) la generalización de las rutas más cortas también puede aplicarse para identificarlas.

Para calcular las puntuaciones de interdete de los nodos, a continuación se muestra un código de muestra para producir las tres tablas anteriores utilizando el paquete de R de tnet.
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Manually enter the example network
net <- cbind(
i=c(1,1,2,2,2,2,3,3,4,5,5,6),
j=c(2,3,1,3,4,5,1,2,2,2,6,5),
w=c(4,2,4,1,4,2,2,1,4,2,1,1))
# Calculate the binary betweenness measure
betweenness_w(net, alpha=0)
# Calculate the first generation weighted betweenness measure
betweenness_w(net, alpha=1)
# Calculate the first generation weighted betweenness measure
betweenness_w(net, alpha=0.5)

 Nota: La implementación del algoritmo de Brandes (2001) encuentra múltiples rutas si tienen exactamente la misma distancia. Por ejemplo, si se encuentra un camino sobre el empate directo con un peso de 1 (distancia = 1/1 = 1) y un segundo camino es a través de un nodo intermediario con dos empates con pesos de 2 (distancia = 1/2 + 1 / 2 = 1), las dos rutas tienen exactamente la misma distancia. Sin embargo, si hay un tercer camino a través de dos intermediarios con tres vínculos con pesos de 3 (distancia = 1/3 + 1/3 + 1/3), no es exactamente igual a 1 ya que las computadoras leen estos valores como 0.3333333 y la suma de estos valores es 0.9999999. Por lo tanto, esta ruta se considera más corta que las otras dos rutas (distancia = 1).

Referencias

Barrat, A., Barthelemy, M., Pastor-Satorras, R., Vespignani, A., 2004. The architecture of complex weighted networks. Proceedings of the National Academy of Sciences 101 (11), 3747-3752. arXiv:cond-mat/0311416
Brandes, U., 2001. A Faster Algorithm for Betweenness Centrality. Journal of Mathematical Sociology 25, 163-177.
Dijkstra, E. W., 1959. A note on two problems in connexion with graphs. Numerische Mathematik 1, 269-271.
Freeman, L. C., 1978. Centrality in social networks: Conceptual clarification. Social Networks 1, 215-239.
Freeman, L. C., Borgatti, S. P., White, D. R., 1991. Centrality in valued graphs: A measure of betweenness based on network flow. Social Networks 13 (2), 141-154.
Newman, M. E. J., 2001. Scientific collaboration networks. II. Shortest paths, weighted networks, and centrality. Physical Review E 64, 016132.
Opsahl, T., Agneessens, F., Skvoretz, J. (2010). Node centrality in weighted networks: Generalizing degree and shortest paths. Social Networks 32, 245-251. 

sábado, 16 de junio de 2018

Centralidad en redes de dos modos


Centralidad de nodo en redes de dos modos

Tore Opsahl

La centralidad de los nodos, o la identificación de qué nodos son más "centrales" que otros, ha sido un tema clave en el análisis de redes (Freeman, 1978). Freeman (1978) argumentó que los nodos centrales eran aquellos "en el meollo de las cosas" o puntos focales. Con base en este concepto, formalizó tres medidas: grado, cercanía y entrecruzamiento. Para obtener una información más completa sobre estas medidas, vea Centralidad de nodos en Redes ponderadas.

Grado

Grado es el número de vínculos que tiene un nodo o el número de otros nodos a los que está conectado un nodo. En redes de dos modos, este concepto se puede aplicar directamente. Sin embargo, hay algunas complicaciones. En redes de dos modos, "la cantidad de otros nodos a los que está conectado un nodo" es ambigua. Podría ser el número de nodos secundarios a los que está conectado un nodo primario (y viceversa), o el número de nodos primarios a los que está conectado un nodo primario. Para aclarar la diferencia entre estos dos números, me referí a ellos como nodos de dos modos y un modo, respectivamente. Para ejemplificar la diferencia, la imagen a continuación muestra la red local que rodea a Flora en el Dataset de mujeres sureñas de Davis (1940) (adaptado de Opsahl, 2011).





La red local que rodea a Flora
Como se puede ver en este diagrama, el grado de dos modos de Flora es 2 y el grado de 1 modo es 12. Si la red se proyectó a una red de modo único, la medida de grado estándar sería 12.

También es posible obtener el grado de dos modos de los nodos una vez que se ha proyectado una red utilizando el método de Newman (2001). Este método de proyección fue desarrollado para las redes de coautoría científica, y establece el peso del empate entre dos autores igual a la suma en los trabajos co-autoescritos de 1 sobre el número de autores en ese documento menos 1. En otras palabras, para cada coautoría papel, un nodo divide 1 por los otros autores. Como tal, el peso total del empate es igual al número de documentos coautores. La única diferencia entre este método y el grado de dos modos son los trabajos de autor único. Estos están excluidos en el primero e incluidos en el segundo método.

Cercanía e intermediación

La parte principal de las medidas de proximidad y de interdependencia son los caminos más cortos y su longitud. La cercanía es la suma inversa de las longitudes de las trayectorias más cortas, y la interdependencia es la cantidad de trayectos más cortos que pasan por un nodo. Al aprovechar el algoritmo de ruta más corta de dos modos, es posible ampliar fácilmente estas dos medidas a redes de dos modos. Para recapitular rápidamente este algoritmo: 
  1. Use un método de proyección apropiado 
  2. Utilice el método para identificar las rutas más cortas y calcular su longitud en redes ponderadas de modo único (Brandes, 2001; Dijkstra, 1959; Newman, 2001).
Cuando se encuentre la longitud de las rutas más cortas, la medida de proximidad sería simplemente la suma inversa de ellas. Del mismo modo, la interdependencia se calculará fácilmente mirando los nodos intermedios en las rutas más cortas y contará, para cada nodo, la cantidad de veces que ese nodo es un intermediario. Nota: si hay varias rutas más cortas, es importante dividir por el número de ellas para asegurarse de que cada ruta solo cuente una vez.


Ejemplo

Para ilustrar las cuatro medidas, confío en Davis (1940) Southern Women Dataset. La asistencia a la reunión de 18 mujeres en 14 reuniones se registra en este conjunto de datos. La siguiente tabla muestra el resultado de las cuatro medidas (Newman's, 2001, el método de proyección se utiliza para la cercanía y la interdependencia, ya que es probable que el nivel de interacción entre los participantes en eventos más pequeños sea mayor).

.
nodo two-mode degree one-mode degree closeness betweenness
EVELYN 8 17 0.053 5
LAURA 7 15 0.051 1
THERESA 8 17 0.060 48
BRENDA 7 15 0.050 1
CHARLOTTE 4 11 0.044 0
FRANCES 4 15 0.041 0
ELEANOR 4 15 0.043 0
PEARL 3 16 0.037 0
RUTH 4 17 0.043 0
VERNE 4 17 0.045 0
MYRNA 4 16 0.042 0
KATHERINE 6 16 0.052 0
SYLVIA 7 17 0.054 11
NORA 8 17 0.059 60
HELEN 5 17 0.046 0
DOROTHY 2 16 0.027 0
OLIVIA 2 12 0.035 0
FLORA 2 12 0.035 0

En esta tabla se puede ver una limitación clave de la medida de transición: la mayoría de las personas obtiene un puntaje de 0 (es decir, la medida es cero-inflado). Las correlaciones por pares entre las medidas se informan a continuación. Si bien todas las medidas tienen altas correlaciones, es interesante observar que la medida de grado de dos modos tiene una mayor correlación con la cercanía y la interdependencia que la medida de grado de modo único. Esto podría sugerir que la medida de grado de dos modos computacionalmente barata es más capaz de replicar las medidas de proximidad y de equilibrio computacionalmente costosas.


1 2 3 4
1: two-mode degree 1.00


2: one-mode degree 0.51 1.00

3: closeness 0.95 0.44 1.00
4: betweenness 0.59 0.34 0.64 1.00


¿Quieres probarlo con tus datos?

Las medidas se pueden calcular utilizando tnet. Primero, necesita descargar e instalar tnet en R. Luego, necesita crear un edgelist de su red (vea las estructuras de datos en tnet para redes de dos modos). Los siguientes comandos muestran cómo se crearon las tablas anteriores.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# Load tnet and the Southern Women Dataset
library(tnet)
data(tnet)
net <- Davis.Southern.women.2mode
 
# Calculate two-mode degree
out <- degree_tm(net, measure="degree")
 
# Create one-mode projection
net1 <- projecting_tm(net, "Newman")
 
# Calculate one-mode degree
tmp <- degree_w(net1)[,"degree"]
 
# Append to table
out <- data.frame(out, onemodedegree=tmp)
 
# Calculate closeness and append to table
tmp <- closeness_w(net1 )[,"closeness"]
out <- data.frame(out, closeness=tmp)
 
# Calculate betweenness and append to table
tmp <- betweenness_w(net1 )[,"betweenness"]
out <- data.frame(out, betweenness=tmp)
 
# Download and set names
out[,"node"] <- read.table("http://opsahl.co.uk/tnet/ datasets/Davis_southern_club_women-name.txt")
 
# Pair-wise correlation table
tmp <- matrix(nrow=4, ncol=4)
tmp[lower.tri(tmp)] <- apply(which(lower.tri(tmp), arr.ind=TRUE)+1, 1, function(a) cor.test(out[,a[1]], out[,a[2]])$estimate)




Referencias

Brandes, U., 2001. A Faster Algorithm for Betweenness Centrality. Journal of Mathematical Sociology 25, 163-177.
Davis, A., Gardner, B. B., Gardner, M. R., 1941. Deep South. University of Chicago Press, Chicago, IL.
Dijkstra, E. W., 1959. A note on two problems in connexion with graphs. Numerische Mathematik 1, 269-271.
Freeman, L. C., 1978. Centrality in social networks: Conceptual clarification. Social Networks 1, 215-239.
Newman, M. E. J., 2001. Scientific collaboration networks. II. Shortest paths, weighted networks, and centrality. Physical Review E 64, 016132.
Opsahl, T., 2013. Triadic closure in two-mode networks: Redefining the global and local clustering coefficients. Social Networks 35, doi:10.1016/j.socnet.2011.07.001.
Opsahl, T., Agneessens, F., Skvoretz, J., 2010. Node centrality in weighted networks: Generalizing degree and shortest paths. Social Networks 32 (3), 245-251.

viernes, 12 de mayo de 2017

Las redes sociales de la Guerra de las Galaxias

Las redes sociales de Star Wars: ¿quién es el personaje central?

Data Scientist examina las 6 películas de Star Wars para extraer las redes sociales, dentro de cada película y en todo el universo Star Wars. La estructura de la red revela algunas diferencias sorprendentes entre las películas, y encuentra quién es realmente el carácter central.

Por Evelina Gabasova, U. de Cambridge.
KD Nuggets


Logo de Star WarsAlgunos de nosotros estamos esperando la Navidad, y algunos de nosotros estamos esperando la nueva película en la franquicia de Star Wars, The Force Awakens. Mientras tanto, decidí mirar el ciclo completo de 6 películas desde un punto de vista cuantitativo y extraer las redes sociales de Star Wars, tanto dentro de cada película como en todo el universo Star Wars. Mirar la estructura de la red social revela algunas diferencias sorprendentes entre la trilogía original y las precuelas.

Si está interesado en los detalles técnicos de cómo extraí los datos, diríjase a la sección How I did the analysis. Pero empecemos con algunas visualizaciones.

Esta es la red social de las 6 películas combinadas:



Puede abrir la red en una ventana completa que mostrará una visualización interactiva de la red en la que puede arrastrar nodos individuales. Si coloca el cursor sobre los nodos individuales, verá el nombre del carácter correspondiente.

Aquí los nodos representan a los personajes de las películas. Los personajes están conectados por un enlace si ambos hablan en la misma escena. Y cuanto más los personajes hablan juntos, más grueso es el vínculo entre ellos. El tamaño de cada nodo corresponde al número total de escenas en las que aparece el personaje. Hice algunas decisiones discutibles: Anakin y Darth Vader están representados por dos nodos separados, porque esta distinción es importante para la historia. Por otra parte, el nodo Emperador también representa conjuntamente Palpatine y Darth Sidious. También fusioné Amidala con Padme.

La trilogía original (episodios IV, V y VI) de la derecha está mayormente separada en la red de la trilogía prequel a la izquierda porque la mayoría de los personajes aparecen sólo en una de las trilogías. Los nodos cruciales que conectan las dos redes son Obi-Wan Kenobi, R2-D2 y C-3PO. Especialmente los robots parecen jugar una función social importante porque aparecen con frecuencia a través de todas las películas.

Las estructuras de las dos sub-redes son también diferentes. La trilogía original tiene menos nodos importantes (Luke, Han, Leia, Chewbacca, Darth Vader) y están densamente interconectados entre sí. La trilogía prequel tiene más nodos en general, con muchas más conexiones. Voy a ver películas individuales con más detalle más adelante en el post.


Líneas de tiempo del personaje

Muchos de los personajes aparecen en varias películas, por lo que también he creado una comparación de sus líneas de tiempo a través de los episodios individuales. Los siguientes gráficos muestran dónde se mencionan los caracteres individuales en los guiones de película. En orden de aparición, estos son los plazos de algunos de los personajes principales:



Aquí incluí todas las menciones de cada personaje, que incluye otros personajes que discuten su nombre. Es interesante ver cómo Anakin aparece simultáneamente con Darth Vader durante el Episodio III, y luego Darth Vader se hace cargo. Anakin vuelve a aparecer hacia el final del Episodio VI cuando Darth Vader se aleja del lado Oscuro.

Los personajes que aparecen más consistentemente en todas las películas son los mismos que están en el centro de la red social - Obi-Wan, C-3PO y R2-D2. Yoda y el emperador también aparecen en todas las películas, pero no hablan directamente con muchas personas en la trilogía original, lo que les mueve fuera del centro en la red social.

Redes en películas individuales
Ahora veamos las redes en películas individuales. Observe cómo el número de nodos y la complejidad de las redes cambian entre los prequels y las películas originales. De nuevo, aparece un enlace entre caracteres si hablan dentro de la misma escena.

Episodio I: La amenaza fantasma




Episodio II: El ataque de los clones




Episodio III: La venganza de los Sith





Episodio IV: Una nueva esperanza




Episodio V: El Imperio Contraataca






Episodio VI: El retorno del Jedi





Importancia de los caracteres

Las redes individuales muestran nuevamente que la trilogía precuela tiene más caracteres y más interacciones en general. Los episodios originales tienen menos personajes, pero interactúan más entre sí.

George Lucas dijo:

Realmente es la historia de la tragedia de Darth Vader, y comienza cuando tiene nueve años, y termina cuando está muerto.
(fuente)

Pero, ¿es Darth Vader / Anakin realmente el personaje central? Vamos a utilizar algunos métodos de análisis de redes para ver quién es realmente importante en las historias y sus estructuras sociales.

Calculé dos medidas de importancia en las redes para cada una de las películas:


  • Centralidad de grado - esto es simplemente el número de conexiones que tiene el nodo en la red. En las películas de Star Wars, esto corresponde al número total de escenas en las que cada personaje habla.
  • Intermediación - esta medida mira cuántos caminos más cortos en la red conducen a través del nodo. Por ejemplo, imagina que eres Leia y quieres enviar un mensaje a Greedo - el camino más corto para enviarlo es a través de Han Solo, porque interactuó tanto con Leia como con Greedo. Por otro lado, si quieres enviar un mensaje a Luke, no tienes que pasar por Han porque Leia conoce a Luke directamente. La centralidad intermedia para Han se calcula usando el número de caminos más cortos entre todos los otros caracteres que pasan a través de él.

Las dos medidas muestran la importancia de un personaje en la red. La centralidad del grado muestra cuánta gente interactúa cada personaje directamente. El intermedio se refiere más a la forma integral de cada uno de los personajes es a la historia. Los personajes con alta interrelación conectan diferentes áreas de la red social.

Para ambas medidas, los valores más altos significan más importancia. Aquí están los 5 primeros caracteres para cada película:

Episodio I

NombreGrado
1.QUI-GON26
2.ANAKIN23
3.JAR JAR19
4.R2-D219
5.PADME18
NombreIntermediación
1.QUI-GON91.7
2.JAR JAR46.6
3.EMPEROR41.8
4.R2-D230.9
5.NUTE GUNRAY27.2

Episodio II

NombreGrado
1.ANAKIN21
2.OBI-WAN19
3.PADME17
4.YODA10
5.MACE WINDU10
NombreIntermediación
1.OBI-WAN64.7
2.PADME56.5
3.MACE WINDU12.7
4.JAR JAR8.3
5.EMPEROR6.8

Episodio III

NombreGrado
1.ANAKIN14
2.OBI-WAN13
3.BAIL ORGANA12
4.EMPEROR11
5.PADME10
NombreIntermediación
1.OBI-WAN22.7
2.EMPEROR19.0
3.PADME8.0
4.R2-D26.7
5.BAIL ORGANA4.5

Parece que Anakin es en general el personaje más conectado en las tres primeras películas, basado en su grado. Sin embargo, no es muy integral a las relaciones en las películas! Su puntuación de intermediación es tan pequeña que nunca llega a los primeros 5 personajes. Esto significa que todos los otros personajes interactúan directamente entre sí y no a través de Anakin. ¿Cómo buscan las mismas medidas para la trilogía original?

Episodio IV

NombreGrado
1.LUKE15
2.LEIA12
3.C-3PO10
4.CHEWBACCA9
5.HAN8
NombreIntermediación
1.LUKE32.7
2.LEIA19.7
3.HAN15.0
4.C-3PO13.2
5.CHEWBACCA8.0


Episodio V

NombreGrado
1.LUKE12
2.DARTH VADER12
3.HAN11
4.R2-D211
5.C-3PO10
NombreIntermediación
1.LUKE25.2
2.DARTH VADER11.3
3.LEIA9.7
4.HAN6.7
5.R2-D24.5


Episodio VI

NombreGrado
1.LUKE15
2.R2-D212
3.C-3PO11
4.LEIA9
5.HAN9
NombreIntermediación
1.LUKE24.3
2.C-3PO23.0
3.DARTH VADER18.5
4.CHEWBACCA16.0
5.LANDO5.5

Aquí ambas medidas de centralidad muestran resultados muy similares - Luke es el personaje más central de todas las películas, y usando ambas medidas. El orden de los caracteres basado en las dos medidas es casi el mismo.

El análisis de centralidad cuantifica algunas de las cosas que pudimos ver en las redes sociales. La trilogía precuela tiene estructuras sociales más complejas, con más personajes interconectados. Esto también lleva al hecho de que Anakin no es tan central para la historia - algunas de las historias suceden junto con la historia de Anakin, o involucrar a Anakin sólo en el lado. Por otro lado, la trilogía original tiene una estructura más ajustada. Hay un menor número de personajes centrales y vinculan la historia juntos - esto resulta en el acuerdo entre el grado y las medidas de centralidad entremedias.

Quizás esto es parte de la razón por la cual la trilogía original es más popular - las tramas son más consistentes y conducidas por los personajes principales. Las precuelas tienen una estructura más descentralizada y no hay un héroe claro. Aunque las historias están unidas por Anakin, no vincula a los otros personajes.

¿Cómo se ven las medidas cuando miramos la red social completa de todos los episodios juntos? Miré dos variantes de la red. En el primero Anakin y Darth Vader aparecen como dos individuos separados, en el segundo los uní en una sola persona.

Red conjunta 1

Anakin y Darth Vader separados

NombreGrado
1.ANAKIN42
2.R2-D241
3.OBI-WAN37
4.PADME34
5.C-3PO31
NombreIntermediación
1.OBI-WAN370.4
2.PADME237.3
3.R2-D2236.7
4.C-3PO222.9
5.LUKE194.4

Red conjunta 2

Anakin y Darth Vader fusionados

NombreGrado
1.DARTH VADER59
2.R2-D241
3.OBI-WAN37
4.PADME34
5.C-3PO31
NombreIntermediación
1.OBI-WAN348.7
2.C-3PO303.1
3.DARTH VADER241.5
4.R2-D2227.6
5.PADME226.2

Si nos fijamos en Anakin y Darth Vader por separado, Anakin sigue siendo el personaje más conectado, pero no es central en la red. Si los unimos, las cosas mejoran un poco. Ahora Darth Vader / Anakin es el tercer personaje más importante en términos de intermediación. En general, las redes sociales parecen mostrar que las películas de Star Wars están realmente unidas entre sí por Obi-Wan Kenobi en lugar de Darth Vader.

Cómo hice el análisis

Como esto es parte del calendario F# Advent calendar, usé F# para la mayor parte del análisis. Lo combiné con D3.js para las visualizaciones de redes sociales, y con R para el análisis de centralidad de red. Puedes encontrar todo el código fuente en mi GitHub.  Debido a que el código completo resultó ser relativamente largo, aquí sólo veo algunas de las partes más interesantes.


Analizando los guiones

Empecé descargando todos los guiones para las 6 películas de Star Wars. Están disponibles gratuitamente en la The Internet Movie Script Database (IMSDb), por ejemplo aquí está el guión para el episodio IV: The New Hope. Los guiones son sólo en forma de borradores que a veces difieren de las películas reales - las diferencias, sin embargo, no son muy grandes.

El primer paso fue analizar los guiones. Para complicar las cosas, cada uno de ellos utiliza un formato ligeramente diferente. Los guiones estaban en HTML, dentro de las etiquetas <td class = "srctext"> </ td> o dentro de las etiquetas <pre> </ pre>. Para extraer el contenido de cada secuencia de comandos, he utilizado el analizador Html de F # biblioteca de datos que permite el acceso a las etiquetas individuales en un documento HTML utilizando declaraciones como

open FSharp.Data
let url = "http://www.imsdb.com/scripts/Star-Wars-A-New-Hope.html"
HtmlDocument.Load(url).Descendants("pre")
The full code for this part is available in the parseScripts.fs file.
The next step was to extract relevant information from the scripts. In general, a script looks like this:
INT. GANTRY - OUTSIDE CONTROL ROOM - REACTOR SHAFT

Luke moves along the railing and up to the control room.

[...]
                LUKE
        He told me enough!  It was you 
        who killed him.

                VADER
        No.  I am your father.

    Shocked, Luke looks at Vader in utter disbelief.

                LUKE
        No.  No.  That's not true!  
        That's impossible!
Each scene starts with its setting: INT. (interior) or EXT. (exterior) and the location of the scene. Then there can be some free text describing what is happening and how does the scene look. In the dialogues, the names of characters are written in capital letters (sometimes also in bold), followed by what they are saying.
The main signposts in the screenplay are the INT. and EXT. statements which serve as scene separators. These were written consistently in bold in all the 6 scripts and I used them to split them into individual scenes:
// split the script by scene
// each scene starts with either INT. or EXT. 
let recsplitByScene (script : string[]) scenes =
    let scenePattern = "<b>[0-9]*(INT.|EXT.)"
    let idx = 
        onmouseover="showTip(event, 'fs4', 10)" onmouseout="hideTip(event, 'fs4', 10)">script 
        |> Seq.tryFindIndex (fun line -> Regex.Match(line, scenePattern).Success)
    match idx with
    | Some i ->
        let remainingScenes = script.[i+1 ..]
        let currentScene = script.[0..i-1]
        splitByScene remainingScenes (currentScene :: scenes)
    | None -> script :: scenes
This is a recursive function that takes the full screenplay and looks for the specific pattern, which is EXT. or INT. in bold, optionally preceded by a scene number. The function goes through the string and when it encounters the scene break, it splits the string into the current scene and the remaining text. Then it runs recursively until all the scenes are extracted, using the scenes variable as an accumulator.

Getting list of characters

The previous function gave me a list of scenes for each of the movies. Extracting the characters out of them turned out to be more difficult. Some of the scenes followed the format that I showed in the example above, some of the scenes only used character names followed by a colon and their dialogue, all within the same line in the text. The only common property between the different formats was that the names were always written in capital letters.
I resorted to regular expressions, one for each screenplay format:
// Extract names of characters that speak in scenes. 
// A) Extract names of characters in the format "[name]:"
let getFormat1Names text =
    let matches = Regex.Matches(text, "[/A-Z0-9-]+*:")
    let names = 
        seq { for m in matches -> m.Value }
        |> Seq.map (fun name -> name.Trim([|' '; ':'|]))
        |> Array.ofSeq
    names

// B) Extract names of characters in the format "<b> [name] </b>"
let getFormat2Names text =
    let m = Regex.Match(text, "<b>[]*[/A-Z0-9-]+[]*</b>")
    if m.Success then
        let name = m.Value.Replace("<b>","").Replace("</b>","").Trim()
        [| name |]
    else [||]


Cada una de las expresiones regulares coincide no sólo con mayúsculas, sino también con números, hypens, espacios y barras. Todo porque los personajes de Star Wars usan nombres como "R2-D2" o incluso "FODE / BEED".

Para extraer realmente la lista de caracteres que aparecen a través de las películas, también tuve que tener en cuenta el hecho de que muchos personajes usan varios nombres. El senador Palpatine se convierte en Darth Sidious y luego en The Emperor, Amidala se disfraza de Padme (o al revés?).

Debido a esto, he creado manualmente un archivo simple aliases.csv donde especificé qué nombres considero que son los mismos. Utilicé éstos como asignación en un nombre único para cada carácter (excepto Anakin y Darth Vader).


let aliasFile = __SOURCE_DIRECTORY__ + "/data/aliases.csv"
// Use csv type provider to access the csv file with aliases
type Aliases = CsvProvider<aliasFile>

/// Dictionary for translating character names between aliases
let aliasDict = 
    Aliases.Load(aliasFile).Rows 
    |> Seq.map (fun row -> row.Alias, row.Name)
    |> dict

/// Map character names onto unique set of names
let mapName name = if aliasDict.ContainsKey(name) then aliasDict.[name] else name

/// Extract character names from the given scene
let getCharacterNames (scene: string []) =
    let names1 = scene |> Seq.collect getFormat1Names 
    let names2 = scene |> Seq.collect getFormat2Names 
    Seq.append names1 names2
    |> Seq.map mapName
    |> Seq.distinct
Now I could finally extract names of characters from the individual scenes! The following function extracts all the names of characters from all the screenplay urls.
let allNames =
  scriptUrls
  |> List.map (fun (episode, url) ->
    let script = getScript url
    let scriptParts = script.Elements()

    let mainScript = 
        scriptParts
        |> Seq.map (fun element -> element.ToString())
        |> Seq.toArray

    // Now every element of the list is a single scene
    let scenes = splitByScene mainScript [] 

    // Extract names appearing in each scene
    scenes |> List.map getCharacterNames |> Array.concat )
  |> Array.concat
  |> Seq.countBy id
  |> Seq.filter (snd >> (<) 1)  // filter out characters that speak in only one scene
The only remaining problem was that many of the names were not actual names. The list was full of people called “PILOT” or “OFFICER” or “CAPTAIN”. After this I manually went through the results and filtered out the names that were actual names. This resulted in the characters.csv file.

Interactions between characters

To construct the social networks, I wanted to extract all the occasions when two characters talk to each other. This happens if two characters speak within the same scene (I decided to ignore situations when people talk with each other over a transmitter, and therefore across scenes). Extracting characters that are part of the same dialogue was now similified because I could just look at the list of characters I put together in the previous step.
let characters = 
    File.ReadAllLines(__SOURCE_DIRECTORY__ + "/data/characters.csv") 
    |> Array.append (Seq.append aliasDict.Keys aliasDict.Values |> Array.ofSeq)
    |> set
Here I created a set of all character names and their aliases to use for lookup and filtering. Then I used it to search through the characters appearing in each scene:
let scenes = splitByScene mainScript [] |> List.rev

let namesInScenes = 
    scenes 
    |> List.map getCharacterNames
    |> List.map (fun names -> names |> Array.filter (fun n -> characters.Contains n))
Then I used the filtered list of characters to define the social network:
// Create weighted network
let nodes = 
    namesInScenes 
    |> Seq.collect id
    |> Seq.countBy id        
    // optional threshold on minimum number of mentions
    |> Seq.filter (fun (name, count) -> count >= countThreshold)

let nodeLookup = nodes |> Seq.map fst |> set

let links = 
    namesInScenes 
    |> List.collect (fun names -> 
        [ for i in 0..names.Length - 1 do 
            for j in i+1..names.Length - 1 do
                let n1 = names.[i]
                let n2 = names.[j]
                if nodeLookup.Contains(n1) && nodeLookup.Contains(n2) then
                    // order nodes alphabetically
                    yield min n1 n2, max n1 n2 ])
    |> Seq.countBy id


Esto me dio una lista de nodos con el número de veces que hablaron en todo el script, que utilizó para especificar el tamaño de los nodos en las visualizaciones. Entonces creé un enlace para cada vez que dos personajes hablaban dentro de la misma escena, y los contaba para obtener la fuerza de cada relación. Juntos, los nodos y enlaces definieron la red social completa.

Finalmente, exporté los datos al formato JSON. Puedes encontrar todas las redes, tanto globales como individuales, en mi Github.
El código completo para este paso está en el script getInteractions.fsx.

El personaje menciona en el guión

También decidí mirar donde cada uno de los personajes aparece a lo largo del ciclo de seis películas, lo que resulta en el gráfico de líneas de tiempo. Para esto miré todas las veces que el nombre del personaje fue mencionado en los guiones, no limitado al número de veces que el personaje habló. El código para esto era mucho más similar a la extracción de las interacciones en la sección anterior, sólo aquí estaba buscando todas las menciones y no sólo para los diálogos. Para obtener los cronogramas actuales, también mantuve un registro de los números de escena. El fragmento de código siguiente devuelve una lista de números de escena y caracteres que se mencionan en ellos.
let scenes = 
    splitByScene mainScript [] |> List.rev
let totalScenes = scenes.Length

scenes
|> List.mapi (fun sceneIdx scene -> 
    // some names contain typos with lower-case characters
    let lscene = scene |> Array.map (fun s -> s.ToLower()) 

    characters
    |> Array.map (fun name -> 
        lscene 
        |> Array.map (fun contents -> if containsName contents name then Some name else None )
        |> Array.choose id)
    |> Array.concat
    |> Array.map (fun name -> mapName (name.ToUpper()))
    |> Seq.distinct 
    |> Seq.map (fun name -> sceneIdx, name)
    |> List.ofSeq)
|> List.collect id,
totalScenes


Para obtener la línea de tiempo completa, utilicé los números de escena para mapear cada episodio en un intervalo [índice de episodios-1, índice de episodios], dándome una escala relativa de dónde en el episodio apareció el personaje. Los tiempos de escena en intervalos [0,1] son del Episodio I, en [1,2] corresponden al Episodio II, etc.

// extract timelines
[0 .. 5]
|> List.map (fun episodeIdx -> getSceneAppearances episodeIdx)
|> List.mapi (fun episodeIdx (sceneAppearances, total) ->
    sceneAppearances 
    |> List.map (fun (scene, name) -> 
        float episodeIdx + float scene / float total, name))


Guardé estos datos en un archivo pseudo-csv mal formateado, donde cada fila contiene un nombre de carácter y los tiempos relativos que el carácter apareció a través de las 6 películas, separados por comas.

El código completo está en el archivo getMentions.fsx.



Resumen

Como con la mayoría de las tareas de la ciencia de datos, el paso más difícil aquí era conseguir los datos en una buena forma. Los guiones de Star Wars tenían formatos ligeramente diferentes, así que pasé la mayor parte del tiempo averiguando las propiedades comunes de los documentos HTML para crear una función común para analizarlos y para identificar los nombres de los personajes. Después de eso, fue sólo una pequeña pelea para Wookiee y la igualdad droide cuando decidí combinar fuentes de datos para inferir sus conexiones sociales. Hice las redes extraídas disponibles en JSON en mi GitHub así que usted puede también jugar con ellas.



Enlace
Código fuente: github.com/evelinag/StarWars-social-network
Extracted networks in JSON format: github.com/evelinag/StarWars-social-network/tree/master/networks
Screenplays: imsdb.com