🔬 Research Hypotheses

Theoretical formulation and statistical framework for content analysis validation

All hypotheses were derived from the integration of Framing Theory and Protection Motivation Theory (PMT) and were tested using chi-square tests of independence and logistic regression models.

H1 Perceived Severity

Articles dominated by the Disaster frame will be more likely to exhibit higher levels of Perceived Severity than articles dominated by other primary frames.

Independent Variable (IV): Primary Frame (Disaster vs. all other frames)
Dependent Variable (DV): Perceived Severity (Strong vs. Non-Strong)
Statistical Test: Pearson’s chi-square test; logistic regression analysis

H2 Response Efficacy

Articles dominated by the Prevention frame will be more likely to exhibit moderate or strong Response Efficacy than articles dominated by other primary frames.

Independent Variable (IV): Primary Frame (Prevention vs. all other frames)
Dependent Variable (DV): Response Efficacy (Moderate/Strong vs. Weak/Absent)
Statistical Test: Pearson’s chi-square test; logistic regression analysis

H3 Self-Efficacy

Articles that include at least one Protective Recommendation will be more likely to exhibit moderate or strong Self-Efficacy than articles without such recommendations.

Independent Variable (IV): Presence of Protective Recommendation (Yes/No)
Dependent Variable (DV): Self-Efficacy (Moderate/Strong vs. Weak/Absent)
Statistical Test: Pearson’s chi-square test; logistic regression analysis

H4 Threat–Coping Configuration

Articles characterized by an Alarmist emotional tone and the absence of Protective Recommendations will be more likely to combine high Perceived Severity with absent or weak Self-Efficacy than other configurations.

Independent Variable (IV): Combined condition (Alarmist tone + No recommendation vs. other combinations)
Dependent Variable (DV): Threat–Coping configuration (High Severity + Low/Absent Self-Efficacy vs. other patterns)
Statistical Test: Pearson’s chi-square test; logistic regression analysis

H5 Institutional Sourcing

Articles in which Authorities are the dominant source type will be more likely to adopt a Prevention frame than articles in which Citizens/Population are the dominant source type.

Independent Variable (IV): Dominant Source Type (Authorities vs. Citizens/Population)
Dependent Variable (DV): Primary Frame (Prevention vs. all other frames)
Statistical Test: Pearson’s chi-square test; logistic regression analysis

H6 Newspaper Systematic Differences

There will be systematic differences between newspapers, such that La Voz de Galicia will use the Response frame more frequently than Público, while Público will use the Scientific/Technical frame more frequently than La Voz de Galicia.

Independent Variable (IV): Newspaper (Público vs. La Voz de Galicia)
Dependent Variable (DV): Primary Frame (Response and Scientific/Technical frames)
Statistical Test: Pearson’s chi-square test; logistic regression analysis

H7 Threat–Efficacy Balance Subset

Among articles characterized by high perceived threat, those that include at least one Protective Recommendation will be more likely to be classified as High Threat / High Efficacy than as High Threat / Low Efficacy.

Independent Variable (IV): Presence of Protective Recommendation (Yes/No), within high-threat subset
Dependent Variable (DV): Threat–Efficacy Balance (High Threat / High Efficacy vs. High Threat / Low Efficacy)
Statistical Test: Pearson’s chi-square test (subset analysis); logistic regression analysis
Analytical Strategy & Replication Code

All hypotheses were tested using a two-stage analytical strategy. First, bivariate associations were examined using Pearson’s chi-square tests of independence. Second, logistic regression models were estimated to assess the robustness of observed relationships. Effect sizes were reported using Cramér’s V where appropriate. Cases of sparse cell counts, convergence warnings, or perfect separation were explicitly reported and considered in the interpretation of results.

All statistical calculations were performed in Python, and the code used for the analyses is provided below:

View Python Replication Code (Click to expand)
import pandas as pd
import numpy as np
from scipy import stats
import statsmodels.api as sm
import statsmodels.formula.api as smf

# =========================
# 1) LOAD DATA
# =========================
df = pd.read_csv("csv/banco-2026-05-21_94837.csv")

# Keep original column names with accents and spaces
COLS = {
    "newspaper": "Newspaper",
    "primary_frame": "Primary Frame",
    "emotional_tone": "Predominant Emotional Tone",
    "source_type": "Dominant Source Type",
    "severity": "Perceived Severity",
    "vulnerability": "Perceived Vulnerability",
    "response_efficacy": "Perceived Response Efficacy",
    "self_efficacy": "Perceived Self-Efficacy",
    "balance": "Threat–Efficacy Balance",
    "recommendation": "Protective Recommendation",
}

# =========================
# 2) HELPERS
# =========================
def cramers_v(chi2, table):
    n = table.to_numpy().sum()
    r, c = table.shape
    return np.sqrt(chi2 / (n * (min(r - 1, c - 1))))

def chi_square_test(data, var1, var2):
    table = pd.crosstab(data[var1], data[var2])
    chi2, p, dof, expected = stats.chi2_contingency(table)
    v = cramers_v(chi2, table)
    return table, chi2, p, dof, v

def logistic_binomial(data, y_col, x_col):
    """
    Fits a simple logistic regression: y ~ x
    """
    formula = f"{y_col} ~ {x_col}"
    model = smf.logit(formula, data=data).fit(disp=0)
    
    params = model.params
    conf = model.conf_int()
    or_vals = np.exp(params)
    or_ci_low = np.exp(conf[0])
    or_ci_high = np.exp(conf[1])
    pvals = model.pvalues
    
    out = pd.DataFrame({
        "term": params.index,
        "coef": params.values,
        "OR": or_vals.values,
        "CI_low": or_ci_low.values,
        "CI_high": or_ci_high.values,
        "p": pvals.values
    })
    return model, out

# =========================
# 3) RECODINGS FOR HYPOTHESES
# =========================

# H1: Disaster frame -> strong perceived severity
df["H1_x"] = (df[COLS["primary_frame"]] == "Disaster").astype(int)
df["H1_y"] = (df[COLS["severity"]] == "Strong").astype(int)

# H2: Prevention frame -> moderate/strong response efficacy
df["H2_x"] = (df[COLS["primary_frame"]] == "Prevention").astype(int)
df["H2_y"] = df[COLS["response_efficacy"]].isin(["Moderate", "Strong"]).astype(int)

# H3: Protective recommendation -> moderate/strong self-efficacy
df["H3_x"] = (df[COLS["recommendation"]] == "Sim").astype(int)
df["H3_y"] = df[COLS["self_efficacy"]].isin(["Moderate", "Strong"]).astype(int)

# H4: Alarmist tone + no recommendation -> High Threat / Low Efficacy
df["H4_x"] = (
    (df[COLS["emotional_tone"]] == "Alarmist") &
    (df[COLS["recommendation"]] == "Não")
).astype(int)
df["H4_y"] = (df[COLS["balance"]] == "High Threat / Low Efficacy").astype(int)

# H5: Authorities vs Citizens/Population -> Prevention frame
df_h5 = df[df[COLS["source_type"]].isin(["Authorities", "Population/Citizens"])].copy()
df_h5["H5_x"] = (df_h5[COLS["source_type"]] == "Authorities").astype(int)
df_h5["H5_y"] = (df_h5[COLS["primary_frame"]] == "Prevention").astype(int)

# H6: Newspaper differences
# Part A: Response frame
df["H6a_x"] = (df[COLS["newspaper"]] == "La Voz de Galicia").astype(int)
df["H6a_y"] = (df[COLS["primary_frame"]] == "Response").astype(int)

# Part B: Scientific/Technical frame
df["H6b_x"] = (df[COLS["newspaper"]] == "Público").astype(int)
df["H6b_y"] = (df[COLS["primary_frame"]] == "Scientific/Technical").astype(int)

# H7: among high-threat articles, recommendation -> High Threat / High Efficacy
df_h7 = df[df[COLS["balance"]].str.contains("High Threat", na=False)].copy()
df_h7["H7_x"] = (df_h7[COLS["recommendation"]] == "Sim").astype(int)
df_h7["H7_y"] = (df_h7[COLS["balance"]] == "High Threat / High Efficacy").astype(int)

# =========================
# 4) RUN TESTS
# =========================
results = []

# H1
table, chi2, p, dof, v = chi_square_test(df, "H1_x", "H1_y")
model, logit_df = logistic_binomial(df, "H1_y", "H1_x")
results.append({
    "Hypothesis": "H1", "Test": "Chi-square", "N": int(table.to_numpy().sum()),
    "Chi2": chi2, "df": dof, "p": p, "CramersV": v, "Decision": "supported" if p < 0.05 else "not supported"
})
results.append({
    "Hypothesis": "H1", "Test": "Logistic", "N": len(df), "OR": np.exp(model.params["H1_x"]),
    "CI_low": np.exp(model.conf_int().loc["H1_x"])[0], "CI_high": np.exp(model.conf_int().loc["H1_x"])[1], "p": model.pvalues["H1_x"]
})

# H2
table, chi2, p, dof, v = chi_square_test(df, "H2_x", "H2_y")
model, logit_df = logistic_binomial(df, "H2_y", "H2_x")
results.append({
    "Hypothesis": "H2", "Test": "Chi-square", "N": int(table.to_numpy().sum()),
    "Chi2": chi2, "df": dof, "p": p, "CramersV": v, "Decision": "supported" if p < 0.05 else "not supported"
})
results.append({
    "Hypothesis": "H2", "Test": "Logistic", "N": len(df), "OR": np.exp(model.params["H2_x"]),
    "CI_low": np.exp(model.conf_int().loc["H2_x"])[0], "CI_high": np.exp(model.conf_int().loc["H2_x"])[1], "p": model.pvalues["H2_x"]
})

# H3
table, chi2, p, dof, v = chi_square_test(df, "H3_x", "H3_y")
model, logit_df = logistic_binomial(df, "H3_y", "H3_x")
results.append({
    "Hypothesis": "H3", "Test": "Chi-square", "N": int(table.to_numpy().sum()),
    "Chi2": chi2, "df": dof, "p": p, "CramersV": v, "Decision": "supported" if p < 0.05 else "not supported"
})
results.append({
    "Hypothesis": "H3", "Test": "Logistic", "N": len(df), "OR": np.exp(model.params["H3_x"]),
    "CI_low": np.exp(model.conf_int().loc["H3_x"])[0], "CI_high": np.exp(model.conf_int().loc["H3_x"])[1], "p": model.pvalues["H3_x"]
})

# H4
table, chi2, p, dof, v = chi_square_test(df, "H4_x", "H4_y")
model, logit_df = logistic_binomial(df, "H4_y", "H4_x")
results.append({
    "Hypothesis": "H4", "Test": "Chi-square", "N": int(table.to_numpy().sum()),
    "Chi2": chi2, "df": dof, "p": p, "CramersV": v, "Decision": "supported" if p < 0.05 else "not supported"
})
results.append({
    "Hypothesis": "H4", "Test": "Logistic", "N": len(df), "OR": np.exp(model.params["H4_x"]),
    "CI_low": np.exp(model.conf_int().loc["H4_x"])[0], "CI_high": np.exp(model.conf_int().loc["H4_x"])[1], "p": model.pvalues["H4_x"]
})

# H5
table, chi2, p, dof, v = chi_square_test(df_h5, "H5_x", "H5_y")
model, logit_df = logistic_binomial(df_h5, "H5_y", "H5_x")
results.append({
    "Hypothesis": "H5", "Test": "Chi-square", "N": int(table.to_numpy().sum()),
    "Chi2": chi2, "df": dof, "p": p, "CramersV": v, "Decision": "supported" if p < 0.05 else "not supported"
})
results.append({
    "Hypothesis": "H5", "Test": "Logistic", "N": len(df_h5), "OR": np.exp(model.params["H5_x"]),
    "CI_low": np.exp(model.conf_int().loc["H5_x"])[0], "CI_high": np.exp(model.conf_int().loc["H5_x"])[1], "p": model.pvalues["H5_x"]
})

# H6a Response frame
table, chi2, p, dof, v = chi_square_test(df, "H6a_x", "H6a_y")
model, logit_df = logistic_binomial(df, "H6a_y", "H6a_x")
results.append({
    "Hypothesis": "H6a", "Test": "Chi-square", "N": int(table.to_numpy().sum()),
    "Chi2": chi2, "df": dof, "p": p, "CramersV": v, "Decision": "supported" if p < 0.05 else "not supported"
})
results.append({
    "Hypothesis": "H6a", "Test": "Logistic", "N": len(df), "OR": np.exp(model.params["H6a_x"]),
    "CI_low": np.exp(model.conf_int().loc["H6a_x"])[0], "CI_high": np.exp(model.conf_int().loc["H6a_x"])[1], "p": model.pvalues["H6a_x"]
})

# H6b Scientific/Technical frame
table, chi2, p, dof, v = chi_square_test(df, "H6b_x", "H6b_y")
model, logit_df = logistic_binomial(df, "H6b_y", "H6b_x")
results.append({
    "Hypothesis": "H6b", "Test": "Chi-square", "N": int(table.to_numpy().sum()),
    "Chi2": chi2, "df": dof, "p": p, "CramersV": v, "Decision": "supported" if p < 0.05 else "not supported"
})
results.append({
    "Hypothesis": "H6b", "Test": "Logistic", "N": len(df), "OR": np.exp(model.params["H6b_x"]),
    "CI_low": np.exp(model.conf_int().loc["H6b_x"])[0], "CI_high": np.exp(model.conf_int().loc["H6b_x"])[1], "p": model.pvalues["H6b_x"]
})

# H7
table, chi2, p, dof, v = chi_square_test(df_h7, "H7_x", "H7_y")
model, logit_df = logistic_binomial(df_h7, "H7_y", "H7_x")
results.append({
    "Hypothesis": "H7", "Test": "Chi-square", "N": int(table.to_numpy().sum()),
    "Chi2": chi2, "df": dof, "p": p, "CramersV": v, "Decision": "supported" if p < 0.05 else "not supported"
})
results.append({
    "Hypothesis": "H7", "Test": "Logistic", "N": len(df_h7), "OR": np.exp(model.params["H7_x"]),
    "CI_low": np.exp(model.conf_int().loc["H7_x"])[0], "CI_high": np.exp(model.conf_int().loc["H7_x"])[1], "p": model.pvalues["H7_x"]
})

# =========================
# 5) SAVE OUTPUTS
# =========================
results_df = pd.DataFrame(results)
results_df.to_csv("H1_H7_results.csv", index=False)
print(results_df)