This repository contains sample codes for the methodology described in the research paper:
๐ Investigating Echo-Chambers in Decentralized Social Networks: A Mastodon Case Study.
The scripts implement techniques to identify potential echo-chambers on the Mastodon social network by analyzing network structural properties of both original toot networks and reply networks.
The methodology focuses on two primary network types and one influential user analysis:
-
Reply Network Analysis (Context Graphs):
- Context Definition: Conversations in Mastodon, including ancestors and descendants of toots (similar to threads).
- Graph Construction: For each context, a "context graph" is built.
- Nodes: Accounts that replied (descendants) to the original toot within that context.
- Edges: A mutual (two-way) following relationship between two replier accounts.
- Sentiment Analysis: Reply texts are analyzed for sentiment (positive/negative). Context graphs are then divided into positive and negative sentiment subgraphs.
- Echo-Chamber Detection:
- Clustering Coefficient: Applied to each sentiment-based subgraph. An echo-chamber is suspected if a subgraph with nodes sharing the same sentiment has a Clustering Coefficient of 0.5 or higher.
- Inter-Subgraph Connectivity: The absence of links between the positive and negative sentiment subgraphs within the same context is also an indicator of potential echo-chamber formation, as communities with differing views might be isolating themselves.
-
Original Toot Network Analysis:
- Graph Construction: For each sociopolitical hashtag, a graph is created.
- Nodes: Accounts that posted an original toot (not a reply) using the same hashtag.
- Edges: A mutual following relationship between these accounts.
- Analysis: The Clustering Coefficient is applied to this graph to assess the likelihood of echo-chamber formation among original posters. (The paper notes these values were generally low).
- Graph Construction: For each sociopolitical hashtag, a graph is created.
-
Co-follower Matrix and Common Reference Metric (Influential Users):
- Influential User Identification: The top 5 users with the highest degree (and/or betweenness centrality, as per paper) are identified from the original toot network for each hashtag.
- Co-follower Matrix Construction: For these influential users, a matrix is built by counting the number of shared followers between each pair.
- Normalization: Values are normalized using the Cosine Co-Citation formula:
Normalized Co-follower(A, B) = Co-followers(A, B) / sqrt(Followers(A) * Followers(B)) - Normalized Common Reference Metric: This assesses the cumulative number of normalized shared followers among all distinct pairs of influential users:
Normalized Common Reference = sum(Normalized Co-follower(i, j)) / N(where N is the number of unique pairs) (The paper notes these values were also generally low).
The codebase and generated data are organized as follows:
Mastodon_Echo_Chambers/contexts/{HASHTAG}_context/: Stores data related to Mastodon contexts (conversations/threads).{CONTEXT_ID}_context.json: Raw JSON data for a specific context, including ancestor and descendant toots.{CONTEXT_ID}_context_repliers/: Contains followings lists for each replier in that context.{REPLIER_ID}_replier_followings.json: JSON list of accounts followed by a specific replier.
followers/: (General storage) Stores follower lists for specific users if fetched individually.{USER_ID}_followers.json: JSON list of followers for a given user ID.
followings/: (General storage) Stores following lists for specific users if fetched individually.{USER_ID}_followings.json: JSON list of accounts a given user ID is following.
graphs/{HASHTAG}_graphs/: Stores generated network graphs for reply networks in GEXF format.{CONTEXT_ID}.gexf: The graph of repliers for a specific context, where edges represent mutual followings. Nodes may be annotated with sentiment scores.
graphs/{HASHTAG}_root_graphs/: Stores generated network graphs for original toot networks.{HASHTAG}.gexf: The graph of original posters for a hashtag.
hashtags/: Contains JSON files with lists of statuses (toots) collected for specific hashtags.{HASHTAG}.json: List of toots for the given hashtag.
images/{HASHTAG}_images/: Stores visualizations of the context graphs.{CONTEXT_ID}.png: Visualization of the full context graph of repliers.{CONTEXT_ID}_sentiment.png: Visualization of the positive and negative sentiment subgraphs for a context.
images/{HASHTAG}_root_images/: Stores visualizations of the original toot graphs.{HASHTAG}.png: Visualization of the original toot network for the hashtag.
roots/{HASHTAG}_roots/: Stores followings and followers lists for users who posted original toots related to a hashtag.{USER_ID}_root_followings.json: JSON list of accounts followed by an original poster.{USER_ID}_root_followers.json: JSON list of followers of an original poster (used for co-citation analysis).
texts/{HASHTAG}_texts/{CONTEXT_ID}_context/: Stores the text content of replies.{REPLIER_ID}.txt: Text of replies made by a specific replier within a context, used for sentiment analysis.
The analysis pipeline is executed through a series of Python scripts:
-
Data Collection:
get_hashtag_statuses.py: Fetches toots (statuses) for specified hashtags from the Mastodon API and saves them to thehashtags/directory.parse_date.py: Utility script for parsing date strings from Mastodon API responses.count_root_replies.py: (Optional utility) Counts replies for root statuses to understand data volume.get_contexts.py: For each relevant toot, fetches its full context (ancestors and descendants) and saves it tocontexts/{HASHTAG}_context/.get_followings.py: Core function to retrieve the list of accounts a given user is following. Used by other scripts.get_followers.py: Core function to retrieve the list of followers for a given user. Used by other scripts.- For Reply Networks:
get_followings_of_repliers.py: Iterates through contexts and, for each replier (descendant), fetches their followings list. Saves data tocontexts/{HASHTAG}_context/{CONTEXT_ID}_context_repliers/.collect_replies_text.py: Extracts the textual content of replies from the collected context data and saves them into individual text files intexts/{HASHTAG}_texts/{CONTEXT_ID}_context/.
- For Original Toot Networks & Influential User Analysis:
get_followings_of_roots.py: Fetches followings lists for users who posted original toots and saves them toroots/{HASHTAG}_roots/as{USER_ID}_root_followings.json.get_followers_of_repliers.py: Note: Despite its name, this script fetches followers for root tooters (original posters) identified inhashtags/{HASHTAG}.jsonand saves them toroots/{HASHTAG}_roots/as{USER_ID}_root_followers.json. This data is used for the co-follower analysis.
-
Graph Construction:
create_repliers_graph.py: Constructs the "context graphs" for reply networks based on mutual following relationships between repliers. Saves graphs as GEXF files ingraphs/{HASHTAG}_graphs/.create_roots_graph.py: Constructs the original toot network graphs based on mutual following relationships between original posters. Saves graphs tographs/{HASHTAG}_root_graphs/.
-
Sentiment Analysis (for Reply Networks):
sentiment_analysis_vader.py: Reads reply texts fromtexts/, performs sentiment analysis using VADER, and annotates nodes in the GEXF context graphs (graphs/{HASHTAG}_graphs/) with 'pos', 'neg', and 'compound' sentiment scores.
-
Echo-Chamber Detection & Analysis (Reply Networks):
detect_echo_chambers.py:- Loads sentiment-annotated context graphs.
- Splits graphs into positive and negative sentiment subgraphs (based on the 'compound' score).
- Calculates the Clustering Coefficient for each subgraph.
- Identifies potential echo-chambers based on the paper's criteria (shared sentiment in a subgraph with CC >= 0.5, and/or no connectivity between opposing sentiment subgraphs).
- Visualizes these sentiment-separated subgraphs and saves them.
clustering_coefficient.py:- An alternative/focused script to calculate and visualize Clustering Coefficients for sentiment-based subgraphs in reply networks.
- Note: This script uses a different sentiment splitting logic (based on
abs(positive)vsabs(negative)scores) compared todetect_echo_chambers.py.
-
Influential User Analysis (Original Toot Networks):
co_citation.py:- Loads the original toot network graphs from
graphs/{HASHTAG}_root_graphs/. - Identifies the top 5 most influential users based on degree centrality (the paper also mentions betweenness centrality as a criterion).
- Loads the follower lists for these influential users from
roots/{HASHTAG}_roots/{USER_ID}_root_followers.json. - Calculates the normalized co-citation values for pairs of these influential users and the overall Normalized Common Reference Metric for the hashtag.
- Loads the original toot network graphs from
-
Visualization:
visualize_graphs.py: Provides general functionality to visualize the generated GEXF graphs (both context and root graphs), either with simple node labels or with sentiment attributes (if applicable).
- Python 3.x
- Libraries:
requestsnetworkxmatplotlibbeautifulsoup4vaderSentiment
You can typically install these using pip:
pip install requests networkx matplotlib beautifulsoup4 vaderSentiment
(Consider creating a requirements.txt file for easier dependency management.)
- Configure Hashtags: Modify the
hashtagslist in the relevant Python scripts to specify the sociopolitical hashtags for analysis. - Data Collection:
- Run
get_hashtag_statuses.py. - Run
get_contexts.py. - Run
get_followings_of_repliers.py. - Run
collect_replies_text.py. - Run
get_followings_of_roots.py. - Run
get_followers_of_repliers.py(to gather follower data for original posters for co-citation analysis).
- Run
- Graph Construction:
- Run
create_repliers_graph.py. - Run
create_roots_graph.py.
- Run
- Sentiment Analysis:
- Run
sentiment_analysis_vader.py(annotates reply network graphs).
- Run
- Analysis & Detection:
- For reply network echo-chambers: Run
detect_echo_chambers.py. Optionally, runclustering_coefficient.pyfor a focused CC analysis with a different sentiment split. - For influential user analysis: Run
co_citation.py.
- For reply network echo-chambers: Run
- Visualization:
- Use
visualize_graphs.pyas needed for additional graph visualizations.
- Use
- Contexts (
_context.json): Standard Mastodon API V1 status context format, containing "ancestors" and "descendants" lists of status objects. - Followings/Followers (
_followings.json,_followers.json): A JSON list of Mastodon account objects. - Graphs (
.gexf): Standard GEXF format, viewable with tools like Gephi. Nodes representing repliers in context graphs will have sentiment attributes (pos,neg,compound) aftersentiment_analysis_vader.pyis run. - Hashtag Statuses (
.json): A JSON list of Mastodon status objects. - Reply Texts (
.txt): Plain text files where the first line is the replier's ID, and subsequent lines are their replies within that specific context.
If you use this codebase or methodology, please cite the original research paper: Huitema, I. R., Oskooei, A. R., Aktaล, M. S., & Riveni, M. (2024, December). Investigating Echo-Chambers in Decentralized Social Networks: A Mastodon Case Study. In International Conference on Complex Networks and Their Applications (pp. 316-328). Cham: Springer Nature Switzerland.