Visualization with ySights

This tutorial demonstrates ySights’ built-in visualization capabilities for creating publication-ready plots.

What You’ll Learn

  • Global trends visualization

  • Topic evolution plots

  • Profile similarity visualizations

  • Sentiment and exposure diagnostics

  • Multiplex interaction plots

  • Recommendation system plots

  • Summary and moderation diagnostic charts


[ ]:
from pathlib import Path

from ysights import YDataHandler
from ysights import viz, algorithms
from ysights.algorithms import sentiment_diffusion_metrics
from ysights.algorithms.topics import topic_spread, adoption_rate, peak_engagement_time
import matplotlib.pyplot as plt
import numpy as np

%matplotlib inline

[ ]:
# Initialize data handler and network
from pathlib import Path


def resolve_example_db():
    candidates = [
        Path("ysocial_db.db"),
        Path("../notebooks/ysocial_db.db"),
        Path("../../notebooks/ysocial_db.db"),
        Path("docs/notebooks/ysocial_db.db"),
    ]
    for candidate in candidates:
        if candidate.exists():
            return str(candidate.resolve())
    return "ysocial_db.db"

db_path = resolve_example_db()
ydh = YDataHandler(db_path)
network = ydh.social_network()

2. Topic Visualization

Topic Density Temporal Evolution

Visualize how topic interest evolves over time (requires Plotly).

[ ]:
try:
    fig = viz.topic_density_temporal_evolution(ydh, min_days=15)
    fig.show()
    print("Interactive plot showing topic evolution over time.")
    print("Hover over the heatmap to see detailed information.")
except Exception as e:
    print(f"Could not create plot: {e}")
    print("Make sure plotly is installed: pip install plotly")

3. Summary and Diagnostics

Summary Snapshot

Start with a compact dataset overview before plotting the more detailed views.

[ ]:
summary_frame = ydh.summary_frame()
summary_report = ydh.summary_report()

print("Summary frame:")
print(summary_frame.to_string(index=False))

print("\nCache diagnostics:")
print(ydh.analysis_cache_info())

print("\nRecommended indexes:")
print(ydh.recommended_indexes())

Moderation Hotspots

Visualize the most frequently reported users and posts.

[ ]:
hotspots = ydh.moderation_hotspots(top_n=10)

if hotspots.empty:
    print("No moderation hotspots were found in this database.")
else:
    labels = [f"{row.entity_type}:{row.entity_id}" for row in hotspots.itertuples(index=False)]
    plt.figure(figsize=(10, 6))
    plt.barh(labels, hotspots["report_count"], color="firebrick", alpha=0.8)
    plt.gca().invert_yaxis()
    plt.xlabel("Report count")
    plt.ylabel("Entity")
    plt.title("Top Moderation Hotspots", fontsize=14, fontweight='bold')
    plt.grid(True, alpha=0.3, axis='x')
    plt.tight_layout()
    plt.show()

Topic Lifecycle Scatter

Use lifecycle metrics to compare topic spread, adoption, and peak engagement.

[ ]:
lifecycles = topic_spread(ydh)
adoption_rates = adoption_rate(ydh)
peak_periods = peak_engagement_time(ydh)

topic_ids = list(lifecycles.keys())

if not topic_ids:
    print("No topic lifecycle data is available in this database.")
else:
    spread_values = [lifecycles[topic_id]["post_count"] for topic_id in topic_ids]
    adoption_values = [adoption_rates[topic_id] for topic_id in topic_ids]
    peak_values = [peak_periods[topic_id] for topic_id in topic_ids]

    plt.figure(figsize=(10, 6))
    scatter = plt.scatter(
        adoption_values,
        spread_values,
        c=peak_values,
        cmap="viridis",
        s=90,
        alpha=0.85,
        edgecolor="black",
        linewidth=0.4,
    )
    plt.colorbar(scatter, label="Peak period")
    plt.xlabel("Adoption rate")
    plt.ylabel("Topic spread (post count)")
    plt.title("Topic Lifecycle Snapshot", fontsize=14, fontweight='bold')
    plt.grid(True, alpha=0.3)
    plt.tight_layout()
    plt.show()

4. Profile Similarity Visualization

Profile Similarity Distribution

Visualize the distribution of similarity scores.

[ ]:
similarity = algorithms.profile_topics_similarity(ydh, network)

fig = viz.profile_similarity_distribution([similarity], ['All Users'])
plt.tight_layout()
plt.show()

print("Distribution of profile similarity scores across all users.")

Similarity vs. Network Degree

Analyze the relationship between network position and profile similarity.

[ ]:
fig = viz.profile_similarity_vs_degree([similarity], [network], ["All Users"])
plt.tight_layout()
plt.show()

print("Relationship between user connectivity and profile similarity.")

Binned Similarity per Degree

Show average similarity for users grouped by their network degree.

[ ]:
fig = viz.binned_similarity_per_degree([similarity], [network], ["All Users"], bins=10)
plt.tight_layout()
plt.show()

print("Average similarity scores grouped by network degree bins.")

5. Recommendation System Visualization

Recommendations per Post

Analyze how many times posts are recommended.

[ ]:
fig = viz.recommendations_per_post_distribution(ydh)
plt.tight_layout()
plt.show()

print("Distribution of recommendations per post.")

Recommendations vs. Reactions

Analyze the relationship between recommendations and user reactions.

[ ]:
fig = viz.recommendations_vs_reactions(ydh)
plt.tight_layout()
plt.show()

print("Relationship between number of recommendations and reactions received.")

Recommendations vs. Comments

Analyze how recommendations affect comment engagement.

[ ]:
fig = viz.recommendations_vs_comments(ydh)
plt.tight_layout()
plt.show()

print("Relationship between recommendations and comments.")

6. Semantic, Sentiment, and Multiplex Diagnostics

These plots summarize the newly added semantic and multiplex analytics in compact, notebook-friendly visuals.

Semantic profile snapshot

Plot a few semantic metrics for a representative post.

[ ]:
agent_id = next(iter(ydh.agent_mapping()))
sample_posts = ydh.posts_by_agent(agent_id).get_posts()

if sample_posts:
    sample_post = sample_posts[0]
    post_profile = ydh.post_semantic_profile(sample_post.id)
    semantic_metrics = {
        "lexical_diversity": post_profile["lexical_diversity"],
        "readability_proxy": post_profile["readability_proxy"],
        "punctuation_intensity": post_profile["punctuation_intensity"],
    }

    fig, ax = plt.subplots(figsize=(8, 4))
    ax.bar(semantic_metrics.keys(), semantic_metrics.values(), color="#C85C5C")
    ax.set_title(f"Semantic profile for post {sample_post.id}")
    ax.set_ylabel("Score")
    ax.grid(axis="y", alpha=0.3)
    plt.tight_layout()
    plt.show()
else:
    print("No sample posts were found in this dataset.")

Sentiment diffusion timeline

Plot how sentiment labels and recommended exposures evolve across rounds.

[ ]:
diffusion = sentiment_diffusion_metrics(ydh)
timeline = diffusion["timeline"]

if timeline.empty:
    print("No sentiment timeline data is available in this dataset.")
else:
    fig, ax1 = plt.subplots(figsize=(10, 4))
    ax1.plot(timeline["round"], timeline["positive_posts"], label="Positive posts", color="#2E8B57")
    ax1.plot(timeline["round"], timeline["negative_posts"], label="Negative posts", color="#B22222")
    ax1.plot(timeline["round"], timeline["neutral_posts"], label="Neutral posts", color="#555555")
    ax1.set_xlabel("Round")
    ax1.set_ylabel("Post count")
    ax1.set_title("Sentiment diffusion by round")
    ax1.grid(alpha=0.3)
    ax1.legend(loc="upper left")

    ax2 = ax1.twinx()
    ax2.plot(
        timeline["round"],
        timeline["recommended_exposures"],
        label="Recommended exposures",
        color="#1F77B4",
        linestyle="--",
    )
    ax2.set_ylabel("Recommended exposures")
    ax2.legend(loc="upper right")
    plt.tight_layout()
    plt.show()

Multiplex layer comparison

Compare the edge counts for the available interaction layers and inspect the combined graph diagnostics.

[ ]:
multiplex = ydh.multiplex_metrics()
layer_names = list(multiplex["layer_metrics"].keys())
layer_edge_counts = [multiplex["layer_metrics"][name]["edge_count"] for name in layer_names]

fig, ax = plt.subplots(figsize=(8, 4))
ax.bar(layer_names, layer_edge_counts, color="#4F81BD")
ax.set_title("Interaction layer edge counts")
ax.set_ylabel("Edges")
ax.grid(axis="y", alpha=0.3)
plt.tight_layout()
plt.show()

print("Combined polarization summary:")
print(multiplex["combined_polarization"])

7. Saving Visualizations

Save plots for publications or presentations.