Published October 15, 2026 | Version v1

Political Discourse Dataset Stance on X Posts

Description

Candidate-Affiliation Dataset, Code, and Supplementary Information

Overview

This record accompanies the paper Political Stance Detection on X During the 2024 U.S. Election: A Comparative Study of Classical, Neural, and Transformer Models. It extends the USE24-XD dataset (10.5281/zenodo.22803534) and contains:

  • Dataset: X (Twitter) posts labeled with political candidate affiliation (Trump, Biden_Kamala, Neutral), plus engineered features. The features cover sentiment, hate and misinformation signals, temporal context, engagement, location, and LDA topic tokens.
  • Human evaluation set: 300 posts labeled by two annotators.
  • Code: notebooks for the stance-detection experiments (classical, neural and transformer models) and the run-to-run variance analysis.
  • Supplementary Information (SI): the paper's SI as a PDF, covering model configurations and cross-validation robustness.

Intended uses:

  • Political discourse analysis
  • Temporal dynamics of narratives
  • Stance detection, topic modeling and other NLP tasks

Citation

If you use this dataset or build on it in your research, please cite:

TBD

 
 

Please also cite the source dataset, USE24-XD (10.5281/zenodo.22803534).

Post text and access

This record does not contain raw post text, usernames or author IDs. Each post is identified only by its X post id. The only text-derived content is lda_tokens: lemmatized, stop-word-filtered tokens with no word order.

To get the original post text:

Join on id in both cases. Read id as a string, because it exceeds 64-bit float precision.

Contents

File Description
README.md This file
supplementary_information.pdf Supplementary Information (SI) of the paper
annotation_dataset.csv X (Twitter) posts with labels and engineered features
human_evaluation.csv 300 posts double-annotated by humans
stance_detection_experiment.ipynb Preprocessing, labeling, feature engineering, all models
mlp_variance_analysis.ipynb Seed / 5-fold / bootstrap variance of SBERT + MLP

Data schema: annotation_dataset.csv

Each row is one post. Posts span 2024-10-17 to 2025-07-16.

Column Type Description
id string X post ID (joins to USE24-XD)
candidate_affiliation string Candidate affiliation label: Trump, Biden_Kamala or Neutral
user_state string U.S. state code inferred from the user-provided location, or Non_US
sentiment_score float VADER compound sentiment score in [-1, 1]
sentiment_label string positive, negative or neutral
hate_count int Number of hate-related keywords detected
hate_flag 0/1 1 if hate_count > 0
misinfo_count int Number of misinformation-related patterns detected (e.g. "rigged election", "voter fraud")
misinfo_flag 0/1 1 if misinfo_count > 0
tweet_date date Creation date (UTC), YYYY-MM-DD. Empty for 2 posts whose timestamps could not be parsed.
tweet_hour int Hour of creation (UTC), 0–23
tweet_dayofweek int Day of week, 0 = Monday … 6 = Sunday
engagement_raw int Total engagement: likes + retweets + replies + quotes + bookmarks
engagement_rate float engagement_raw / (impressions + 1)
engagement_rate_log float log1p(engagement_rate)
sensitive_flag 0/1 X's possibly_sensitive flag
lda_tokens list[str] Preprocessed tokens used for topic modeling (Python list literal)

Label distribution

Label Posts Share
Neutral 27,340 48.3%
Trump 22,811 40.3%
Biden_Kamala 6,443 11.4%

Notes

  • Labeling. candidate_affiliation comes from a keyword-and-stance heuristic. Candidate-skewed vocabulary was refined with log-odds ratios and then combined with stance cues. See the "Candidate fan heuristic" section of stance_detection_experiment.ipynb, where this column is named candidate_fan.

  • Temporal period. temporal_period is used as a feature in the experiments. It is not stored in the file; derive it from tweet_date as below. Posts dated 2024-10-17, before the first boundary, have no period.

    temporal_period Dates (UTC)
    election_period 2024-10-18 – 2024-11-04
    election_day 2024-11-05
    post_election 2024-11-06 – 2025-07-16
  • Content warning. lda_tokens contains offensive language, because it reflects the original posts.

Sample rows

id candidate_affiliation user_state sentiment_score sentiment_label hate_count hate_flag misinfo_count misinfo_flag tweet_date tweet_hour tweet_dayofweek engagement_raw engagement_rate engagement_rate_log sensitive_flag lda_tokens
1882403261095043491 Trump Non_US -0.8658 negative 3 1 0 0 2025-01-23 12 3 0 0 0 0 ['moron', 'get', 'ass', 'kick', 'election', ...]
1932964629195731097 Trump CA -0.9482 negative 3 1 1 1 2025-06-12 0 3 2 0.06896551724 0.0666913745 0 ['evidence', 'emerge', 'prove', 'wrongdoing', ...]
1886480963905183809 Trump Non_US -0.9779 negative 3 1 0 0 2025-02-03 18 0 0 0 0 1 ['mean', 'trump', 'deport', 'well', ...]

Loading

import ast, pandas as pd
df = pd.read_csv("annotation_dataset.csv", dtype={"id": str})
df["lda_tokens"] = df["lda_tokens"].apply(ast.literal_eval)
 
 

Human evaluation: human_evaluation.csv

300 posts were sampled from the dataset. Two annotators labeled each post independently, and disagreements were resolved into a final label. Post text is not included; join on id with USE24-XD to view it.

Column Description
id X post ID (joins to annotation_dataset.csv)
annotator_1 Label from annotator 1
annotator_2 Label from annotator 2
final_label Adjudicated label
  • Inter-annotator agreement: 87.3% raw, Cohen's κ = 0.81
  • Agreement between the heuristic candidate_affiliation and final_label: 89.7% (269 / 300)

Code

stance_detection_experiment.ipynb

This notebook implements the full pipeline. All models share the same preprocessing and evaluation setup.

1. Data preprocessing

  • English filter, text normalization and cleaning
  • Removal of URLs, mentions and noise
  • Tokenization and lemmatization
  • Handling of hashtags and emoji
  • Removal of short or empty posts, and de-duplication

2. Feature engineering

  • Text: TF-IDF (unigrams + bigrams) and SBERT sentence embeddings (all-mpnet-base-v2)
  • Sentiment: score in [-1, 1] and label
  • Hate and misinformation signals: keyword-based counts and binary flags
  • Temporal: hour of day, day of week, event-based temporal period
  • Engagement: raw count, normalized rate, log-transformed rate
  • Metadata: state-level user location, platform sensitivity flag
  • Topic modeling: LDA tokens

3. Models

  • Classical:
    • Logistic regression (TF-IDF)
    • Linear SVM
    • Histogram gradient boosting (HGB with SVD)
  • Neural: SBERT (all-mpnet-base-v2) embeddings + MLP classifier
  • Transformer: BERTweet (vinai/bertweet-base), fine-tuned

4. Training setup

  • Stratified split: 64% train, 16% validation, 20% test
  • Training classes balanced by upsampling
  • Early stopping on validation macro-F1
  • Hyperparameter tuning for all models

5. Evaluation

  • Macro-F1 (primary metric)
  • Accuracy
  • Confusion matrices for error analysis

mlp_variance_analysis.ipynb

This notebook measures the run-to-run variability of the SBERT + MLP model. It retrains the model under three protocols:

  1. 10 random seeds on the fixed 64/16/20 split
  2. Stratified 5-fold cross-validation
  3. 2,000-sample bootstrap 95% CIs on the test set

Each feature configuration is compared with the text-only baseline using paired tests with Holm correction. When run, the notebook writes per-run metrics, summary tables and a macro-F1 figure.

MLP settings:

  • Hidden layers [256, 128], dropout 0.5
  • AdamW (lr 5e-4, weight decay 1e-3)
  • Label smoothing 0.1, batch size 128
  • Up to 40 epochs, early-stopping patience 7

Feature configurations:

Config SBERT embedding plus
emb_only — (text only)
A sentiment score/label, hate, misinformation and sensitive flags
A+B A + log engagement rate
A+B+C A+B + user state, is_US, has_US_state
A+B+C+D A+B+C + hour, day of week, temporal period

Supplementary Information: supplementary_information.pdf

The paper's Supplementary Information (6 pages):

  • Appendix A — Model configurations. Original baseline vs. final settings for each model family:
    • Table A1: logistic regression and linear SVM
    • Table A2: MLP variants
    • Table A3: BERTweet
  • Appendix B — Cross-validation robustness. The feature analyses from the main text, repeated with stratified 5-fold cross-validation (64/16/20 within each fold) and the Nadeau–Bengio corrected resampled t-test with Holm correction:
    • Table B4: incremental feature blocks (P, A–D)
    • Table B5: single-feature ablation

How to run

The notebooks start from a full table that includes post text (cleaned_election_tweets.csv). To rebuild it, join this dataset with the USE24-XD post text on id (see Post text and access). Notebook outputs that displayed post text were cleared before release.

pip install pandas numpy scikit-learn scipy torch sentence-transformers transformers vaderSentiment nltk gensim matplotlib seaborn
jupyter notebook stance_detection_experiment.ipynb
 

Ethics and intended use

  • For research on political discourse, stance detection and NLP methods only.
  • Do not use it to identify, profile or target individual users.
  • Location is coarse: it is inferred at the state level from free-text profiles and is often unreliable.
  • Hate and misinformation flags come from simple keyword lists. They are not validated classifiers.
  • Anyone using rehydrated content must follow the X Developer Agreement and Policy.

Files

annotation_dataset.csv

Files (17.5 MB)

Name Size
md5:da6832f0afddbd4035917cdc5e77c1da
14.5 MB Preview Download
md5:23bfd1bf3b6ed21a807bb0e4a6855b4a
14.3 kB Preview Download
md5:104887e08b2d562027df4c26b9f8a9c6
380.7 kB Preview Download
md5:4df1d07942647eb982c0b880eb59fd51
2.4 MB Preview Download
md5:8058e9c87e03b4a0bc38d588e2397022
230.7 kB Preview Download

Additional details

Software

Programming language
Python