Source code for teneto.networkmeasures.temporal_betweenness_centrality
"""Calculates temporal betweenness centrality"""
import numpy as np
from .shortest_temporal_path import shortest_temporal_path
[docs]
def temporal_betweenness_centrality(tnet=None, paths=None, calc='pertime'):
r"""
Returns temporal betweenness centrality per node.
Parameters
-----------
data : array or dict
Temporal network input (graphlet or contact). nettype: 'bu', 'bd'.
calc : str
either 'overtime' or 'pertime'
paths : pandas dataframe
Output of TenetoBIDS.networkmeasure.shortest_temporal_paths
Note
-----
Input should be *either* tnet or paths.
Returns
--------
:close: array
normalized temporal betweenness centrality.
If calc = 'pertime', returns (node,time)
If calc = 'overtime', returns (node)
Notes
--------
Temporal betweenness centrality uses the shortest temporal
paths and calculates betweennesss from it.
Teneto returns a normalized betweenness centrality value,
defined as [Bet-1]_:
.. math::
B_{it} = {1 \over (N-1)(N-2)} \sum_{j = 1; j \neq i}
\sum_{k = 1; k \neq i,j} {\sigma^i_{jkt} \over \sigma_{jk}}
If there is a shortest temporal path from j to k, starting at t that
goes through node i, then :math:`\sigma^i_{jkt}` is 1, otherwise 0.
:math:`\sigma_{jk}` is the total number of paths that exist from j to k.
The remaining part of the equation normalizes by the number of nodes.
If a temporal network is used as input (i.e. not the paths), then teneto
uses :py:func:`.shortest_temporal_path` to calculates the shortest paths.
See :py:func:`.shortest_temporal_path` for more details.
If ``calc=overtime`` then the average B over time is returned.
References
---------
.. [Bet-1]
Tang, J., Musolesi, M., Mascolo, C., Latora, V., & Nicosia, V. (2010).
Analysing Information Flows and Key Mediators through Temporal Centrality
Metrics Categories and Subject Descriptors.
Proceedings of the 3rd Workshop on Social Network Systems.
[`Link https://doi.org/10.1145/1852658.1852661`_]
"""
if tnet is not None and paths is not None:
raise ValueError('Only network or path input allowed.')
if tnet is None and paths is None:
raise ValueError('No input.')
# if shortest paths are not calculated, calculate them
if tnet is not None:
paths = shortest_temporal_path(tnet)
bet = np.zeros([paths[['from', 'to']].max().max() +
1, paths['t_start'].max() + 1])
for row in paths.iterrows():
if (np.isnan(row[1]['path includes'])).all():
pass
else:
nodes_in_path = np.unique(np.concatenate(
row[1]['path includes'])).astype(int).tolist()
nodes_in_path.remove(row[1]['from'])
nodes_in_path.remove(row[1]['to'])
sigmajk = paths[(paths['from'] == row[1]['from']) & (paths['to'] == row[1]['to'])]
sigmajk = sigmajk.dropna(subset=['temporal-distance'])
sigmajk = len(sigmajk)
if len(nodes_in_path) > 0:
bet[nodes_in_path, row[1]['t_start']] += 1 / sigmajk
# Normalise bet
bet = (1 / ((bet.shape[0] - 1) * (bet.shape[0] - 2))) * bet
if calc == 'overtime':
bet = np.mean(bet, axis=1)
return bet