voice plots

This commit is contained in:
2026-02-03 00:12:18 +01:00
parent 97c4b07208
commit a7ee854ed0
3 changed files with 113 additions and 24 deletions

View File

@@ -255,7 +255,7 @@ def _():
mo.md(r""" mo.md(r"""
--- ---
# Brand Character Results (overall) # Brand Character Results
""") """)
return return
@@ -276,7 +276,7 @@ def _(S, data):
return return
@app.cell @app.cell(disabled=True)
def _(): def _():
mo.md(r""" mo.md(r"""
## Character ranking points ## Character ranking points
@@ -311,7 +311,7 @@ def _(S, char_rank):
return return
@app.cell(disabled=True) @app.cell
def _(): def _():
mo.md(r""" mo.md(r"""
### Statistical Significance Character Ranking ### Statistical Significance Character Ranking
@@ -335,7 +335,7 @@ def _(S, char_rank):
return return
@app.cell @app.cell(disabled=True)
def _(): def _():
mo.md(r""" mo.md(r"""
## Character Ranking: times 1st place ## Character Ranking: times 1st place
@@ -438,7 +438,7 @@ def _():
return return
@app.cell @app.cell(disabled=True)
def _(): def _():
return return
@@ -461,20 +461,34 @@ def _():
@app.cell @app.cell
def _(): def _():
mo.md(r""" mo.md(r"""
## 8 Most Chosen ## Top 8 Most Chosen out of 18
""") """)
return return
@app.cell @app.cell
def _(S, data): def _(S, data):
v_18_8_3 = S.get_18_8_3(data)[0].collect() v_18_8_3 = S.get_18_8_3(data)[0]
return (v_18_8_3,) return (v_18_8_3,)
@app.cell @app.cell
def _(S, v_18_8_3): def _(S, v_18_8_3):
S.plot_voice_selection_counts(v_18_8_3) S.plot_voice_selection_counts(v_18_8_3, title="Top 8 Voice Selection from 18 Voices", x_label='Voice')
return
@app.cell
def _():
mo.md(r"""
## Top 3 most chosen out of 8
""")
return
@app.cell
def _(S, v_18_8_3):
S.plot_top3_selection_counts(v_18_8_3, title="Top 3 Voice Selection Counts from 8 Voices", x_label='Voice')
return return
@@ -497,10 +511,7 @@ def _(S, data):
@app.cell @app.cell
def _(S, top3_voices): def _(S, top3_voices):
_plot = S.plot_ranking_distribution(top3_voices, x_label='Voice') S.plot_ranking_distribution(top3_voices, x_label='Voice', title="Distribution of Voice Rankings (1st, 2nd, 3rd)")
mo.md(f"""
{mo.ui.altair_chart(_plot)}
""")
return return
@@ -548,7 +559,7 @@ def _():
return return
@app.cell @app.cell(hide_code=True)
def _(): def _():
mo.md(r""" mo.md(r"""
## Weighted Popularity Scores ## Weighted Popularity Scores
@@ -568,6 +579,7 @@ def _(S, top3_voices_weighted):
@app.cell @app.cell
def _(): def _():
## Voice Ranked 1st the most
return return
@@ -578,7 +590,8 @@ def _(top3_voices_weighted):
@app.cell @app.cell
def _(): def _(S, top3_voices):
S.plot_most_ranked_1(top3_voices, title="Most Popular Voice<br>(Number of Times Ranked 1st)", x_label='Voice')
return return
@@ -597,13 +610,13 @@ def _(S, data):
return (voice_1_10,) return (voice_1_10,)
@app.cell(hide_code=True) @app.cell(disabled=True)
def _(S, voice_1_10): def _(S, voice_1_10):
S.plot_average_scores_with_counts(voice_1_10, x_label='Voice', width=1000, domain=[1,10], title="Voice General Impression (Scale 1-10)") S.plot_average_scores_with_counts(voice_1_10, x_label='Voice', domain=[1,10], title="Voice General Impression (Scale 1-10)")
return return
@app.cell @app.cell(disabled=True)
def _(): def _():
mo.md(r""" mo.md(r"""
### Statistical Significance (Scale 1-10) ### Statistical Significance (Scale 1-10)
@@ -687,5 +700,60 @@ def _(S, voice_1_10):
return return
@app.cell
def _(S, data):
# Get your voice scale data (from notebook)
voice_1_10, _ = S.get_voice_scale_1_10(data)
return (voice_1_10,)
@app.cell
def _(S, voice_1_10):
S.plot_average_scores_with_counts(voice_1_10, x_label='Voice', domain=[1,10], title="Voice General Impression (Scale 1-10)")
return
@app.cell(disabled=True)
def _():
mo.md(r"""
### Statistical Significance (Scale 1-10)
""")
return
@app.cell(disabled=True)
def _(S, voice_1_10):
# Compute pairwise significance tests
pairwise_df, metadata = S.compute_pairwise_significance(
voice_1_10,
test_type="mannwhitney", # or "ttest", "chi2", "auto"
alpha=0.05,
correction="bonferroni" # or "holm", "none"
)
# View significant pairs
# print(pairwise_df.filter(pl.col('significant') == True))
# Create heatmap visualization
_heatmap = S.plot_significance_heatmap(
pairwise_df,
metadata=metadata,
title="Voice Rating Significance<br>(Pairwise Comparisons)"
)
# Create summary bar chart
_summary = S.plot_significance_summary(
pairwise_df,
metadata=metadata
)
mo.md(f"""
{mo.ui.altair_chart(_heatmap)}
{mo.ui.altair_chart(_summary)}
""")
return
if __name__ == "__main__": if __name__ == "__main__":
app.run() app.run()

View File

@@ -385,13 +385,13 @@ class QualtricsPlotsMixin:
def plot_ranking_distribution( def plot_ranking_distribution(
self, self,
data: pl.LazyFrame | pl.DataFrame | None = None, data: pl.LazyFrame | pl.DataFrame | None = None,
title: str = "Rankings Distribution\n(1st to 4th Place)", title: str = "Rankings Distribution\n(1st to 3rd Place)",
x_label: str = "Item", x_label: str = "Item",
y_label: str = "Number of Votes", y_label: str = "Number of Votes",
height: int | None = None, height: int | None = None,
width: int | str | None = None, width: int | str | None = None,
) -> alt.Chart: ) -> alt.Chart:
"""Create a stacked bar chart showing the distribution of rankings (1st to 4th).""" """Create a stacked bar chart showing the distribution of rankings (1st to 3rd)."""
df = self._ensure_dataframe(data) df = self._ensure_dataframe(data)
stats = [] stats = []
@@ -401,15 +401,15 @@ class QualtricsPlotsMixin:
r1 = df.filter(pl.col(col) == 1).height r1 = df.filter(pl.col(col) == 1).height
r2 = df.filter(pl.col(col) == 2).height r2 = df.filter(pl.col(col) == 2).height
r3 = df.filter(pl.col(col) == 3).height r3 = df.filter(pl.col(col) == 3).height
r4 = df.filter(pl.col(col) == 4).height # r4 = df.filter(pl.col(col) == 4).height
total = r1 + r2 + r3 + r4 total = r1 + r2 + r3
if total > 0: if total > 0:
label = self._clean_voice_label(col) label = self._clean_voice_label(col)
stats.append({'item': label, 'rank': 'Rank 1 (Best)', 'count': r1, 'rank1': r1}) stats.append({'item': label, 'rank': 'Rank 1 (Best)', 'count': r1, 'rank1': r1})
stats.append({'item': label, 'rank': 'Rank 2', 'count': r2, 'rank1': r1}) stats.append({'item': label, 'rank': 'Rank 2', 'count': r2, 'rank1': r1})
stats.append({'item': label, 'rank': 'Rank 3', 'count': r3, 'rank1': r1}) stats.append({'item': label, 'rank': 'Rank 3', 'count': r3, 'rank1': r1})
stats.append({'item': label, 'rank': 'Rank 4 (Worst)', 'count': r4, 'rank1': r1}) # stats.append({'item': label, 'rank': 'Rank 4 (Worst)', 'count': r4, 'rank1': r1})
if not stats: if not stats:
return alt.Chart(pd.DataFrame({'text': ['No data']})).mark_text().encode(text='text:N') return alt.Chart(pd.DataFrame({'text': ['No data']})).mark_text().encode(text='text:N')
@@ -423,8 +423,8 @@ class QualtricsPlotsMixin:
x=alt.X('item:N', title=x_label, sort=alt.EncodingSortField(field='rank1', order='descending')), x=alt.X('item:N', title=x_label, sort=alt.EncodingSortField(field='rank1', order='descending')),
y=alt.Y('count:Q', title=y_label, stack='zero'), y=alt.Y('count:Q', title=y_label, stack='zero'),
color=alt.Color('rank:N', color=alt.Color('rank:N',
scale=alt.Scale(domain=['Rank 1 (Best)', 'Rank 2', 'Rank 3', 'Rank 4 (Worst)'], scale=alt.Scale(domain=['Rank 1 (Best)', 'Rank 2', 'Rank 3'],
range=[ColorPalette.RANK_1, ColorPalette.RANK_2, ColorPalette.RANK_3, ColorPalette.RANK_4]), range=[ColorPalette.RANK_1, ColorPalette.RANK_2, ColorPalette.RANK_3]),
legend=alt.Legend(orient='top', direction='horizontal', title=None)), legend=alt.Legend(orient='top', direction='horizontal', title=None)),
order=alt.Order('rank:N', sort='ascending'), order=alt.Order('rank:N', sort='ascending'),
opacity=alt.condition(selection, alt.value(1), alt.value(0.2)), opacity=alt.condition(selection, alt.value(1), alt.value(0.2)),

View File

@@ -35,4 +35,25 @@ ORIGINAL_CHARACTER_TRAITS = {
"Balanced", "Balanced",
"Efficient", "Efficient",
] ]
}
VOICE_GENDER_MAPPING = {
"V14": "Female",
"V04": "Female",
"V08": "Female",
"V77": "Female",
"V48": "Female",
"V82": "Female",
"V89": "Female",
"V91": "Female",
"V34": "Male",
"V69": "Male",
"V45": "Male",
"V46": "Male",
"V54": "Male",
"V74": "Male",
"V81": "Male",
"V86": "Male",
"V88": "Male",
"V16": "Male",
} }