This RMarkdown tutorial replicates the core analyses in Pan, Xu, and Xu (2024): “Disguised Repression: Targeting Opponents with Non-Political Crimes to Undermine Dissent” The replication, conducted by Jinwen Wu, a predoctoral fellow at Stanford University, is supervised by Professor Yiqing Xu. The replication summarizes the main data analyses from the original paper; please refer to the original paper for a comprehensive understanding of the ideas presented.

Click the Code button in the top right and select Show All Code to reveal all code used in this RMarkdown. Click Show in paragraphs to reveal the code used to generate a finding. The original replication files can be downloaded from here.


The authors investigate how disguised repression reduces backlash and mobilization by undermining political opponents’ moral authority. They conducted an online survey of 1,065 respondents in China in 2022. The results suggest that disguised repression:

  • Decreases public support for the dissent and willingness to engage in dissent.
  • Increases support for repression
  • Increase self-censorship, especially among political activists and critics who have less stringent moral standards.

To examine the external validity of the findings, the authors collect and analyze 13,665,925 Sina Weibo posts from late 2009 to early 2014 focusing on 2013 China’s crackdown on social media “rumor-mongering.”

1 Conceptual Framework

1.1 Causal Mechanism

Past literature has identified two major strategies through which autocrats handle political dissent: Co-optation and Repression (Gandhi and Przeworski 2007; Svolik 2012). The former option can sometimes be costly, especially when the targeted dissidents are high-profile celebrities, while the latter method usually is always believed to cause backlash.

The authors focus on political repression and challenge the conventional wisdom. They found that disguised repression-charging dissidents with non-political crimes unrelated to political activism-can minimize repercussions. The potential causal mechanisms of the two types of repression can be summarized as follows:

Figure 1: Causal Mechanisms - Repression.
Figure 1: Causal Mechanisms - Repression.

1.2 Premise

The authors discuss three scope conditions for a state to exercise disguised repression. First, the state must have sufficient legal capacity with the necessary rules, procedures, and competent agents in place. Second, the incumbent must be able to influence the judicial system to selectively apply laws against dissidents. Third, the criminal justice system must always sustain public credibility. These conditions enable the incumbent to cover political repression under legal disguise while maintaining stability and reducing public opposition.

1.3 Disguised Repression

The authors defined disguised repression as “the act of charging dissidents with non-political crimes that are unrelated to their political activism.” The state can use non-political charges to legitimize punishments by attacking the morality of the dissidents. This strategy has been employed in various authoritarian regimes, especially as they face increasing anti-government protests since the 21st century. Broadly, the authors categorize the common non-political charges into two broad categories: Economic Crimes and Personal/Sexual Conduct. Below are some examples:

  1. Economic Crimes:
  • Thaksin Shinawatra (Thailand): Accused of corruption and abuse of power after a military coup in 2006.
  • Alexei Navalny (Russia): Sentenced between 2012 and 2014 for embezzlement and fraud.
  • Shehbaz Sharif (Pakistan): Arrested in 2020 on corruption charges.
  1. Personal/Sexual Conduct:
  • Anwar Ibrahim (Malaysia): Sentenced to five years in 2015 on a sodomy charge.

In the survey experiment, the authors examine both types of disguised repression.

1.4 Political Mobilization on Social Media

What has triggered wider political dissent and mobilization since the 21st century? One of the most critical factors is the rise internet and social media (Diamond 2010; Enikolopov, Makarin, and Petrova 2020; Steinert-Threlkeld 2017). Digital platforms facilitate information dissemination, decentralize communication, and reduce coordination costs. When blatant repression becomes more visible, it is expected to invite repercussions. Social media data constitutes a crucial component of this public opinion analysis.

2 Research Method

2.1 Experimental Design

To test the impacts of disguised repression on public attitudes and behaviors, the authors recruit 1,065 respondents and apply a quota sampling method to match age, gender, and education marginals with the urban population of China according to the 2010 national census.

First, all participants read the same excerpt of online criticism against the Chinese government by an anonymous key opinion leader (KOL). They then report attitudes toward the dissident and online expression. Next, each participant is randomly assigned to read no or one of the three charges against the dissident. The authors describe the four conditions as the following:

  • Control Condition (No Repression): Respondents receive no information about any punishment.

  • Political Charge (Political Repression): Political crime of spreading harmful information.

  • Personal/Sexual Conduct Charge (Soliciting Prostitutes): Non-political crime of soliciting prostitutes and group licentiousness.

  • Economic Crimes Charge (Tax Evasion): Non-political crime of tax evasion.

After reading the assigned sentences, respondents in three treatment groups answer questions about their attitudes toward the KOL and willingness to protest on behalf of the KOL. The shift in pre-treatment and post-treatment attitudes represents the main outcome of interest.

The experiment concludes by surveying all four groups of participants on sensitive questions regarding criticism targeted at the Chinese government. These responses help to measure the self-censorship effect.

The flow chart below demonstrates the complete experiment procedures.

Flow Chart. Adapted from Figure 1 Figure 2: Flow Chart. Adapted from Figure 1 in Pan et al. (2023).

In the experiment, respondents in the disguised repression treatment groups (Soliciting Prostitutes & Tax Evasion) are more likely to view the arrested dissident as immoral (see Figure 3).

The repression tactics diminish public support for the KOL and reduce their willingness to protest on behalf of the dissident. Non-political charges also increase their approval of state repression against the dissident (Figure 4).

Results from the sensitive question set demonstrate that disguised repression induces self-censorship, particularly among those with less stringent moral standards who are more likely to have engaged in behaviors that can be exploited for repression.

These effects are consistent when controlling for individual characteristics (e.g., gender, age, education level, employment status, income) and provincial fixed effects.

2.2 Observational Study

The authors examine the external validity of these results by analyzing public reactions to the 2013 crackdown on Chinese government critics. They analyze 13,665,925 Sina Weibo posts from late 2009 to early 2014 that mention 28 critics arrested before or during the 2013 crackdown. The 28 selected KOLs are categorized into either the Non−Political or Political Repression group based on their alleged crimes. Between the two groups, the researchers:

  • Compare the volume of Weibo posts mentioning the critics before and after their arrests (Figure 5).
  • Measure public support for critics by analyzing posts calling for their release (Figure 6).
  • Use stance detection to classify posts as supportive or against the critics.

The case study confirms the experimental findings. Public mentions and support decline for critics charged with non-political crimes but increase for those with political charges.

The contrast again suggests that blatant repression can provoke backlash and mobilize dissent. Zooming into the six-month time window, the difference becomes even more salient as the two trends move in opposite directions (Figure 5b). Dissent in support of the vocal critics under disguised repression is lower than dissent on behalf of those targeted by blatant repression, indicating that political charges might have inflamed public opposition as shown in Figure 6.

3 Replicating the Main Findings

3.1 Installing Packages

Several R packages are required for subsequent data analysis and visualization. The code chunk below checks for all required packages and installs the missing ones.

install_all <- function(packages) {
  installed_pkgs <- installed.packages()[, "Package"]
  for (pkg in packages) {
    if (!pkg %in% installed_pkgs) {
      install.packages(pkg)
    }
  }
}

# packages to be installed
packages <- c( "haven", "ggplot2", "interflex", "scales", "dplyr", "lfe", "tidyr", "pander", "stargazer", "lubridate", "scales", "gridExtra", "kableExtra", "pander")
install_all(packages)

After the installation, call to load the packages. Then, load the experiment data. The file is in the data folder titled as disguise.dta in the replication files.

# Clear the environment
rm(list = ls(all = TRUE))

# Load the packages
library(haven)
library(ggplot2)
library(interflex)
library(scales)
library(dplyr)
library(lfe)
library(tidyr)
library(pander)
library(stargazer)
library(lubridate)
library(scales)
library(gridExtra)
library(kableExtra)
library(pander)

# Load data
data <- read_dta("raw/data/disguise.dta", encoding = "latin1")

The outcome variables measure diverse dimensions of public opinion, including attitude toward the KOL (attitude), support for the critic (supportdis), support for repression (supportrep), willingness to dissent on behalf of the critic (dissent), perceived morality of the critic (morality), and self-censorship tendencies (selfcensorship). The distributions of some representative variables are tabulated below.

# Standardize the variables
data <- data %>%
  mutate(
    stddissent = scale(dissent),
    stdsupportdis = scale(supportdis),
    stdsupportrep = scale(supportrep),
    stdstreisandpol = scale(streisandpol),
    stdstreisand = scale(streisand),
    stdselfcensorship = scale(selfcensorship),
    stdselfcensor = scale(selfcensor),
    stdmorality = scale(morality),
    stdattitude = scale(attitude),
    stdaction = scale(action)
  )


variables <- c("dissent", "supportdis", "supportrep", "morality", "attitude")

# Calculate mean and standard deviation
stats <- data %>%
  summarise(across(all_of(variables), list(mean = ~mean(.x, na.rm = TRUE), sd = ~sd(.x, na.rm = TRUE)))) %>%
  pivot_longer(everything(), names_to = c("Variable", ".value"), names_sep = "_") %>%
  mutate(
    mean = round(mean, 2),
    sd = round(sd, 2),
    Variable = factor(Variable, labels = c("Willingness to dissent on behalf of the critic", "Support for the critic", "Support for repression", "Attitude toward the KOL", "Perceived morality of the critic"))
  )


pander(stats, caption = "Distribution of Outcome Variables", justify = c('left', 'right', 'right'))
Distribution of Outcome Variables
Variable mean sd
Support for the critic 0.27 0.44
Attitude toward the KOL 2.77 1.24
Perceived morality of the critic 7.5 2.61
Support for repression 4.68 3.2
Willingness to dissent on behalf of the critic 9.88 3.08

As shown in the table above, the opinion measures have different standard deviations. They are standardized for later analysis.

3.2 Disguised Repression Undermines Dissidents’ Moral Authority

According to the core conceptual framework, charging dissidents with non-political crimes should cause a greater decline in public trust in their morality compared to political crimes. To test this fundamental hypothesis on the causal path, the authors collect people’s evaluations of the dissident’s morality across four groups. The control group that only read the KOL’s excerpt serves as the baseline, with a mean and standard deviation of 0. As shown in the plot below, all three charges prompt respondents to suspect the dissident’s moral authority. Notably, the Soliciting Prostitute treatment induces the most significant decline, followed by the Tax Evasion treatment.

covar <- c("female", "age", "edulv", "minority", "religious", "married", "work", "work_public", "work_report", "ccp", "income", "eng", "socialmedia", "class")

# Extract coefficients and standard errors
extract_coef <- function(model, treatment) {
  coef_name <- paste("factor(treatment)", treatment, sep = "")
  if (coef_name %in% rownames(summary(model)$coefficients)) {
    coef_est <- coef(model)[coef_name]
    se <- summary(model)$coefficients[coef_name, "Std. Error"]
  } else {
    coef_est <- NA
    se <- NA
  }
  return(c(coef_est, se))
}

  formula_1 <- as.formula(paste("stdmorality ~ factor(treatment) +", paste(covar, collapse = " + "), "| sprov_1"))

KOL_3 <- felm(formula_1, data = data)

#Figure 3(a)
coef_d1 <- extract_coef(KOL_3, 1)
coef_d2 <- extract_coef(KOL_3, 2)
coef_d3 <- extract_coef(KOL_3, 3)
coef_d4 <- extract_coef(KOL_3, 4)

# Prepare data for plotting
plot_3 <- data.frame(
  Group = factor(c("Control", "Political", "Tax Evasion", "Soliciting Prostitutes"),
                 levels = c("Control", "Political", "Tax Evasion", "Soliciting Prostitutes")),
  Estimate = c(coef_d1[1], coef_d2[1], coef_d3[1], coef_d4[1]),
  SE = c(coef_d1[2], coef_d2[2], coef_d3[2], coef_d4[2])
)

# Plot for Figure 3
plot_3 <- ggplot(plot_3, aes(x = Group, y = Estimate, ymin = Estimate - 1.96 * SE, ymax = Estimate + 1.96 * SE)) +
  geom_pointrange() +
  theme_minimal() +
  labs(y = "KOL's Morality (STDZ, SD=3.2)", x = "") +
  geom_text(aes(label = sprintf("%.3f\n(%.3f)", Estimate, SE)), vjust = -0.5, position = position_nudge(y = 0.2)) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  ggtitle("Perceived Morality of KOL")

print(plot_3)

Figure 3: KOL’s Morality Plot. Adapted from Figure 3 in Pan et al. (2023).

The results in the plot confirm: respondents perceive the dissident under disguised repression as less moral compared to the blatant repression counterpart.

3.3 Disguised Repression Increase Support for Repression and Disincentivize Backfire

Following the causal mechanism, people are less likely to oppose state actions if they believe the dissidents are immoral. When repression is framed as legitimate and necessary criminal justice, the strategy should reduce support for dissidents. Compared to political charges, non-political crimes appear more credible. (According to the survey, 89% of respondents believe the critic is guilty when charged with non-political crimes.) Consequently, public support for government repression is expected to increase, and people shall be less willing to engage in protest on behalf of the repressed KOL.

The plots below examine this hypothesis focusing on the three outcome variables - Support for the critic, Support for repression, and Dissent on behalf of the critic.

formula_2 <- as.formula(paste("stdsupportdis ~ factor(treatment) +", paste(covar, collapse = " + "), "| sprov_1"))
formula_3 <- as.formula(paste("stdsupportrep ~ factor(treatment) +", paste(covar, collapse = " + "), "| sprov_1"))
formula_4 <- as.formula(paste("stddissent ~ factor(treatment) +", paste(covar, collapse = " + "), "| sprov_1"))


# Define the model for Attitude toward KOL
KOL_2_a <- felm(formula_2, data = data)
KOL_2_b <- felm(formula_3, data = data)
KOL_2_c <- felm(formula_4, data = data)

#Plot 4(a)
coef_a1 <- extract_coef(KOL_2_a, 1)
coef_a2 <- extract_coef(KOL_2_a, 2)
coef_a3 <- extract_coef(KOL_2_a, 3)
coef_a4 <- extract_coef(KOL_2_a, 4)

plot_data_KOL <- data.frame(
  Group = factor(c("Control", "Political", "Tax Evasion", "Soliciting Prostitutes"),
                 levels = c("Control", "Political", "Tax Evasion", "Soliciting Prostitutes")),
  Estimate = c(coef_a1[1], coef_a2[1], coef_a3[1], coef_a4[1]),
  SE = c(coef_a1[2], coef_a2[2], coef_a3[2], coef_a4[2])
)

# Plot for KOL Attitude
plot_KOL <- ggplot(plot_data_KOL, aes(x = Group, y = Estimate, ymin = Estimate - 1.96 * SE, ymax = Estimate + 1.96 * SE)) +
  geom_pointrange() +
  theme_minimal() +
  labs(y = "Attitude toward KOL (STDZ, SD=1.24)", x = "") +
  geom_text(aes(label = sprintf("%.3f\n(%.3f)", Estimate, SE)), vjust = -0.5, position = position_nudge(y = 0.2)) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  ggtitle("(a) Attitude: KOL (1055 Obs.)")

print(plot_KOL)

Figure 4(a): Attitude Toward the KOL. Adapted from Figure 2a in Pan et al. (2023).

Continuing with the same regression design, the control group, with both the mean and standard deviation recorded as 0, serves as the baseline. All three treatments decrease people’s sympathy for the KOL. The Soliciting Prostitute treatment elicits the most adverse attitudes towards the KOL, followed by the Tax Evasion treatment. The resulting pattern aligns with Figure 3.

Next, the authors explore how disguised repression influences public opinion on state actions and motivate potential behavioral responses.

# Extract coefficients for Figure 3(b_1)
coef_b2 <- extract_coef(KOL_2_b, 2)
coef_b3 <- extract_coef(KOL_2_b, 3)
coef_b4 <- extract_coef(KOL_2_b, 4)

plot_data_Repression <- data.frame(
  Group = factor(c("Political (Ref.)", "Tax Evasion", "Soliciting Prostitutes"), 
                 levels = c("Political (Ref.)", "Tax Evasion", "Soliciting Prostitutes")),
  Estimate = c(coef_b2[1], coef_b3[1], coef_b4[1]),
  SE = c(coef_b2[2], coef_b3[2], coef_b4[2])
)

# Extract coefficients for Figure 3(b_2)
coef_c2 <- extract_coef(KOL_2_c, 2)
coef_c3 <- extract_coef(KOL_2_c, 3)
coef_c4 <- extract_coef(KOL_2_c, 4)

plot_data_Dissent <- data.frame(
  Group = factor(c("Political (Ref.)", "Tax Evasion", "Soliciting Prostitutes"), 
                 levels = c("Political (Ref.)", "Tax Evasion", "Soliciting Prostitutes")),
  Estimate = c(coef_c2[1], coef_c3[1], coef_c4[1]),
  SE = c(coef_c2[2], coef_c3[2], coef_c4[2])
)


create_plot <- function(data, y_label, title) {
  ggplot(data, aes(x = Group, y = Estimate, ymin = Estimate - 1.96 * SE, ymax = Estimate + 1.96 * SE)) +
    geom_pointrange() +
    theme_minimal() +
    labs(y = y_label, x = "") +
    geom_text(aes(label = sprintf("%.3f\n(%.3f)", Estimate, SE)), vjust = -1, hjust = 0.5) +
    theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
    ggtitle(title) +
    ylim(-1, 1) +
    geom_text(data = data.frame(Group = "Political (Ref.)", Estimate = 0, SE = 0), 
              aes(x = Group, y = Estimate, label = "0\n(0)"), vjust = 1.5, hjust = 0.5)
}

# Create the plots
plot_Repression <- create_plot(plot_data_Repression, "Attitude toward repression (STDZ, SD=2.61)", "Attitude: Repression (759 Obs.)")
plot_Dissent <- create_plot(plot_data_Dissent, "Dissent on behalf of KOL (STDZ, SD=0.44)", "Dissent (759 Obs.)")

# Arrange the plots side by side
grid.arrange(plot_Repression, plot_Dissent, nrow = 1)

Figure 4(b): Attitude toward the State Action and Willingness to Dissent. Adapted from Figure 2b, 2c in Pan et al. (2023).

The plot on the left demonstrates that disguised repression increases respondents’ support for repressing the critic. The absolute level of support for arresting the dissident is 7.5 on a scale from 0 (“totally unreasonable”) to 10 (“totally reasonable”). Furthermore, the figure on the right indicates that, compared to charging critics with political crimes, charging them with non-political offenses reduces respondents’ willingness to engage in dissent on behalf of the repressed opinion leader.

3.4 Disguised Repression Induces Self-Censorship for Regime Critics

The third expected impact of disguised repression is to increase in self-censorship among critics. According to the conceptual framework, the repression tactic should reinforce self-censorship, especially among dissidents with less stringent moral standards. The authors conducted 15 rounds of regression analysis. The treatment variable categorizes participants into three large groups. For each of these three groups, five separate regression analyses are performed to test whether a participant’s moral standard and political discernment shape the treatment effects.

# Function to run regression and extract coefficients and p-values
run_regression <- function(data, formula, sample_filter = NULL, treatment) {
  if (!is.null(sample_filter)) {
    data <- data %>% filter(eval(parse(text = sample_filter)))
  }
  model <- felm(as.formula(formula), data = data)
  summary_model <- summary(model)
  
  # Check if the coefficients table contains the row for the treatment
  treatment_var <- paste0("factor(treatment == ", treatment, ")TRUE")
  if (!treatment_var %in% rownames(summary_model$coefficients)) {
    return(c(NA, NA))
  }
  
  coef_row <- which(rownames(summary_model$coefficients) == treatment_var)
  coefficients <- summary_model$coefficients[coef_row, 1] # Extract coefficient
  p_value <- summary_model$coefficients[coef_row, 4] # Extract p-value
  return(c(coefficients, p_value))
}

results <- matrix(NA, nrow = 3, ncol = 10)
row_names <- c("Political", "Tax Evasion", "Prostitution")
col_names <- c("Coefficient", " P-value", "Coefficient", " P-value", "Coefficient", " P-value", "Coefficient", " P-value", "Coefficient", " P-value")

# Loop through treatments and sample groups
for (treatment in 2:4) {
  treatment_name <- row_names[treatment - 1]
  formula <- paste("selfcensor ~ factor(treatment == ", treatment, ") + ", paste(covar, collapse = " + "), "| sprov_1")
  
  # Full Sample
  results[treatment - 1, 1:2] <- run_regression(data, formula, NULL, treatment)
  
  # Critics (dsocritic > 1)
  results[treatment - 1, 3:4] <- run_regression(data, formula, "dsocritic > 1", treatment)
  
  # Non-Critics (dsocritic <= 1)
  results[treatment - 1, 5:6] <- run_regression(data, formula, "dsocritic <= 1", treatment)
  
  # Less Morally Stringent Critics (dsocritic > 1 & moral <= 127)
  results[treatment - 1, 7:8] <- run_regression(data, formula, "dsocritic > 1 & moral <= 127", treatment)
  
  # More Morally Stringent Critics (dsocritic > 1 & moral > 127)
  results[treatment - 1, 9:10] <- run_regression(data, formula, "dsocritic > 1 & moral > 127", treatment)
}

# Convert results to a data frame
results_df <- as.data.frame(results)

results_df <- results_df %>%
  mutate(across(where(is.numeric), round, 2))
rownames(results_df) <- row_names
colnames(results_df) <- col_names


kable(results_df, caption = "Self-Censorship") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"),
                full_width = F, 
                position = "center") %>%
  add_header_above(c(" " = 1, "Full Sample(1)" = 2, "Critics(2)" = 2, "Non-Critics(3) " = 2, 
                     "Less Morally Stringent Critics(4)" = 2, "More Morally Stringent Critics(5)" = 2)) %>%
  row_spec(0, bold = TRUE) %>% 
  column_spec(1, bold = TRUE) 
Self-Censorship
Full Sample(1)
Critics(2)
Non-Critics(3)
Less Morally Stringent Critics(4)
More Morally Stringent Critics(5)
Coefficient P-value Coefficient P-value Coefficient P-value Coefficient P-value Coefficient P-value
Political 0.00 0.99 -0.03 0.85 0.10 0.58 -0.09 0.67 0.09 0.74
Tax Evasion -0.02 0.88 -0.04 0.77 0.05 0.79 -0.02 0.93 -0.27 0.28
Prostitution 0.05 0.68 0.29 0.06 -0.15 0.39 0.42 0.04 0.11 0.69

The results above demonstrate the impacts of different charges on respondents’ self-censorship behavior. Column (1), using the full sample data, shows that none of the repression charges significantly drive respondents’ propensity to refute criticism against the regime. Utilizing pre-treatment data to classify critics based on their engagement in criticizing government policies on social media, respondents are categorized into either the Critics or the Non-Critics group. Among the Critics, the authors further identified them as the Less Morally Stringent Critics or the More Morally Stringent Critics.

Column (2) highlights that political and tax evasion charges show positive but statistically insignificant effects on self-censorship, whereas charges related to soliciting prostitutes significantly increase self-censorship at the 0.1 level in the Critics group. For non-critics, as shown in Column (3), none of the charges significantly affect self-censorship.

Column (4) emphasizes that among critics with less stringent moral standards, the effect of charges for soliciting prostitutes on self-censorship is even more pronounced. This effect is less pronounced among critics with more stringent moral standards, as depicted in Column (5). These findings corroborate the hypothesis that disguised repression, especially involving morally compromising charges, is more effective in inducing self-censorship among specific subsets of the population.

3.5 China’s Crackdown on Online Critics in 2013

3.5.1 The Trend of the 2013 Crackdown

In the early 2010s, Weibo served as a vibrant platform for discourse. Social media opinion leaders with substantial followings frequently voiced about social and political matters, often challenging the official stance of the Chinese government. In response to the growing influence of these online critics, the Chinese government initiated a crackdown and arrested several high-profile critics from August to December 2013, ostensibly to combat online rumor-mongering. This crackdown is one of the largest in China over the past two decades, providing significant insights into Chinese political dynamics.

The study identified 28 individuals who were arrested during this period, categorized into those charged with non-political crimes (11 individuals) and those charged with political crimes (17 individuals). The figure below illustrates the number of Weibo posts from March 2010 to March 2014. Prior to the crackdown, mentions of critics later charged with non-political crimes were significantly higher and growing rapidly. However, following the crackdown in September 2013, the volume of posts about these critics dropped sharply. The authors suggest that the decrease may be due to: the banning of the critics’ Weibo accounts, censorship of discussions about the arrests, and reduced support or self-censorship among Weibo users.

weibo_counts <- readRDS("./raw/data/weibo_counts.rds")

# Total counts of Weibo posts about KOLs by day
byday <- weibo_counts %>% group_by(day=floor_date(date1, "day"), polct) %>%
  summarize(amount=n())

byday_total <- weibo_counts %>% 
  group_by(date2=floor_date(as.Date(date1), "day"), polct) %>%
  summarize(total=n())

byday$rate <- byday$amount/byday_total$total

# Total counts of Weibo posts about KOLs
bymonth <- weibo_counts %>% group_by(month=floor_date(date1, "month"), polct) %>%
  summarize(amount=n())

bymonth_total <- weibo_counts %>% 
  group_by(date2=floor_date(as.Date(date1), "month"), polct) %>%
  summarize(total=n())

bymonth$rate <- bymonth$amount/bymonth_total$total

# Theme color for shaded area 
light_color <- "#CDD4D8" # light blue
dark_color <- "#B6D0E2"  # darker blue

# -----Figure 4a: Plotting total posts by groups by day------------------------
freq_month_release <- ggplot(data=bymonth, aes(x = month, y = amount, group = polct, color = polct, shape = polct)) +
  geom_rect(aes(xmin = as.Date("2013-05-01"), xmax = as.Date("2013-08-01"), ymin = -Inf, ymax = Inf), fill = light_color, alpha = 0.1, color = NA) +
  geom_rect(aes(xmin = as.Date("2013-08-01"), xmax = as.Date("2013-11-01"), ymin = -Inf, ymax = Inf), fill = dark_color, alpha = 0.05, color = NA) +
  geom_point(size = 2) +
  scale_x_date(breaks = "3 month", date_labels = "%Y%b", limits = as.Date(c("2010-03-01", "2014-03-01"))) +
  geom_line() +
  scale_y_continuous(labels = comma) +
  geom_vline(xintercept = as.numeric(as.Date("2013-08-01")), linetype = "dashed", lwd = 0.3) + 
  annotate(geom = "text", x = as.Date("2013-09-15"), y = 650000, label = "2013 Crackdown", size = 5, angle = 90) +
  labs(title = "",
       y = "Number of Weibo Posts",
       x = "") + 
  theme_bw() + 
  scale_color_manual(name = "Crimes", labels = c("Non-Political", "Political"), values = c("gray60", "gray30")) +
  scale_shape_manual(name = "Crimes", labels = c("Non-Political", "Political"), values = c(17, 19)) +
  theme(
    legend.position = c(0.3, 0.9), # Adjusted legend position to move it to the left
    legend.direction = "horizontal",
    legend.text = element_text(size = 12),
    legend.title = element_text(size = 12), # Include legend title
    axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0.5),
    axis.text = element_text(size = 15),
    axis.title = element_text(size = 15),
    axis.title.x = element_text(size = 20),
    plot.title = element_text(size = 25)
  )
freq_month_release

Figure 5(a): Weibo Post Citing Dissidents’ Names - Quarterly. Adapted from Figure 4a in Pan et al. (2023).

Interestingly, the number of posts mentioning influencers charged with political crimes increased after the crackdown. While disguised repression effectively reduces online discussion about critics, blatant repression may increase online dissent and support for the arrested individuals.

The figure below zooms in the six-month period from May 1 to October 31, 2013. Daily Weibo post counts are aggregated and log-transformed to reduce volume disparities. The shaded area to the right of the dotted line represents the crackdown period.

# Reload the original dataset 
weibo_counts <- readRDS("./raw/data/weibo_counts.rds")
## -----Figure 4b: Plotting logged posts by groups by day-----------------------

# Custom function to create labels in the format "log(number)" for natural logarithm
log_label <- function(x) {
  scales::comma(10^x)
}
freq_day_release <- ggplot(data=byday, aes(x = day, y = log10(amount), group = polct, color = polct)) +
  geom_rect(aes(xmin = as.Date("2013-05-01"), xmax = as.Date("2013-08-01"), ymin = 0, ymax = 6), fill = light_color, alpha = 0.1, color = NA) +
  geom_rect(aes(xmin = as.Date("2013-08-01"), xmax = as.Date("2013-11-01"), ymin = 0, ymax = 6), fill = dark_color, alpha = 0.05, color = NA) +
  geom_point(aes(shape = polct, color = polct), size = 2) +
  scale_x_date(breaks = "14 day", date_labels = "%b%d", limits = as.Date(c("2013-05-01", "2013-11-01"))) +
  geom_line() +
  scale_y_continuous(labels = log_label, limits=c(0,6)) +
  geom_vline(xintercept = as.numeric(as.Date("2013-08-01")), linetype = "dashed", lwd = 0.3) + 
  annotate(geom = "text", x = as.Date("2013-08-05"), y = 1.2, label = "Crackdown", size =5, angle = 90,colour="gray30") +
  labs(title = "",
       y = "Number of Weibo Posts (Log Scale)",
       x = "") + 
  theme_bw() + scale_color_manual(name = "Crimes", labels = c("Non-Political", "Political"), values = c("gray60", "gray30")) +
  scale_shape_manual(name = "Crimes", labels = c("Non-Political", "Political"), values = c(17, 19)) +
  theme(#text = element_text(family = "sans", size = 16),
    legend.position = c(0.26, 0.9),legend.direction = "horizontal",legend.text=element_text(size=13),
    legend.title=element_text(size=14), legend.background = element_blank(),
    axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0.5),
    strip.text.x = element_text(size =240),
    axis.text=element_text(size=15),
    axis.title=element_text(size=15),
    axis.title.x = element_text(size = 20),
    plot.title = element_text(size = 25))

freq_day_release

Figure 5(b): Weibo Post Citing Dissidents’ Names - Monthly. Adapted from Figure 4b in Pan et al. (2023).

Again, the plot shows that mentions of critics decreased (light gray line) for those charged with non-political crimes, while increased for ones charged with political crimes (dark gray line). Political charges may have sparked online dissent among supporters of the arrested opinion leader.

3.5.2 Backfire

The authors further examine Weibo posts containing both 1) the critic’s name and 2) terms like “release” or “release them” within three months of their arrest to assess public support for the critics and the state action. Out of 5,009 posts preliminarily sorted out by the two conditions, 2,479 were identified as genuine calls for release after manual verification.

The plot below compares the relative frequency of calls for the release of critics targeted by disguised repression (light gray line) versus blatant repression (dark gray line).

# Reload the dataset
weibo_counts <- readRDS("./raw/data/weibo_counts.rds")

bymonth <- weibo_counts %>% 
  group_by(month = floor_date(date1, "month"), polct) %>%
  summarize(amount = sum(releasettln)) # Count dissent posts by group

bymonth_total <- weibo_counts %>% 
  group_by(date2 = floor_date(as.Date(date1), "month"), polct) %>%
  summarize(total = n()) # Count total posts by group

bymonth$rate <- bymonth$amount / bymonth_total$total # Calculate dissent rate

bymonth$lnamount <- log(bymonth$amount + 1) # Calculate dissent rate

# Plot dissent rates by group by month
prop_month_release <- ggplot(data = bymonth, aes(x = month, y = rate, group = polct, color = polct)) +
  geom_point(aes(shape = polct, color = polct), size = 1.5) +
  scale_x_date(breaks = "3 month", date_labels = "%Y%m", limits = as.Date(c("2010-03-01", "2014-03-01"))) +
  geom_rect(aes(xmin = as.Date("2013-05-01"), xmax = as.Date("2013-08-01"), ymin = -Inf, ymax = Inf), fill = light_color, alpha = 0.1, color = NA) +
  geom_rect(aes(xmin = as.Date("2013-08-01"), xmax = as.Date("2013-11-01"), ymin = -Inf, ymax = Inf), fill = dark_color, alpha = 0.05, color = NA) +
  geom_point(size = 2) +
  scale_x_date(breaks = "3 month", date_labels = "%Y%b", limits = as.Date(c("2010-03-01", "2014-03-01"))) +
  geom_line() +
  scale_y_continuous(labels = function(x) paste0(x * 100, "%"), breaks = seq(0, 0.1, 0.02)) +
  geom_vline(xintercept = as.numeric(as.Date("2013-08-01")), linetype = "dashed", lwd = 0.3) + 
  annotate(geom = "text", x = as.Date("2013-06-01"), y = 0.03, label = "2013 Crackdown", size = 6, angle = 90) +
  labs(title = "",
       y = "Proportion of Dissenting Weibo Posts",
       x = "") + 
  theme_bw() + 
  scale_color_manual(name = "Crimes", labels = c("Non-Political", "Political"), values = c("gray60", "gray30")) +
  scale_shape_manual(name = "Crimes", labels = c("Non-Political", "Political"), values = c(17, 19)) +
  theme(legend.position = c(0.25, 0.9),
        legend.direction = "horizontal",
        legend.text = element_text(size = 11),
        legend.title = element_text(size = 12),
        axis.text.x = element_text(angle = 90, hjust = 1),
        strip.text.x = element_text(size = 240),
        axis.text = element_text(size = 15),
        axis.title = element_text(size = 15),
        axis.title.x = element_text(size = 20),
        plot.title = element_text(size = 25))

prop_month_release

Figure 6: Calls for the Critics’ Release. Adapted from Figure 5 in Pan et al. (2023).

As expected, empirical evidence suggests that public dissent is lower for critics targeted by disguised repression compared to those targeted by blatant repression. This trend resonates with the experimental findings presented in Figure 4(b). People are less likely to advocate for dissidents and protest against state action if the critics were arrested under non-political offenses.

Evidence from Figure 5 and Figure 6 both suggest that disguised repression effectively decreases public support for the critic and willingness to engage in dissent.

Lastly, the authors measure the stance of 13,665,925 Weibo posts towards critics using the mDeBERTa model for stance detection. They trained the model on the C-Stance dataset by Zhao, Li, and Caragea (2023) to estimate the proportion of supportive and oppositional posts before and after the crackdown.

Prior to arrests, positive stances towards two groups of critics were similar (42% and 40%). After arrests for political crimes, positive stances increased to 58% and negative stances decreased to 19%. Conversely, for non-political crimes, positive stances dropped to 28% and negative stances increased to 51%.

4 Implications

The study challenges the conventional assumption that repression always generates opposition or fear among the public. The analyses of survey experiments and observational data demonstrate that when repression is disguised as punishment for non-political crimes, public support for dissidents decreases while support for state action increases. The authors suggest that disguised repression undermines the perceived moral authority of dissidents and effectively legitimizes state actions against them. Consequently, this strategic repression reduces dissent, demobilizes followers, and induces self-censorship among activists.

The 2013 crackdown in China serves as a case study illustrating how authoritarian regimes employ disguised repression. While this tactic carries the cost of needing plausible charges, it enhances regime stability and legitimacy over the long term compared to blatant repression. This research offers valuable insights for understanding the dynamics of authoritarian control and public dissent. Future research can explore other framing strategies, such as portraying critics as foreign agents, and investigate broader public attitudes toward repression beyond individual cases.

References

Diamond, Larry. 2010. “Liberation Technology.” Journal of Democracy 21 (3): 69–83.
Enikolopov, Ruben, Alexey Makarin, and Maria Petrova. 2020. “Social Media and Protest Participation: Evidence from Russia.” Econometrica 88 (4): 1479–1514.
Gandhi, Jennifer, and Adam Przeworski. 2007. “Authoritarian Institutions and the Survival of Autocrats.” Comparative Political Studies 40 (11): 1279–1301.
Pan, Jennifer, Xu Xu, and Yiqing Xu. 2024. Disguised Repression: Targeting Opponents with Non-Political Crimes to Undermine Dissent.” The Journal of Politics. https://doi.org/10.2139/ssrn.4488481.
Steinert-Threlkeld, Zachary C. 2017. “Spontaneous Collective Action: Peripheral Mobilization During the Arab Spring.” American Political Science Review 111 (2): 379–403.
Svolik, Milan W. 2012. The Politics of Authoritarian Rule. Cambridge University Press.
Zhao, Chenye, Yingjie Li, and Cornelia Caragea. 2023. “C-STANCE: A Large Dataset for Chinese Zero-Shot Stance Detection.” In Proceedings of the 61st Annual Meeting of the Association for Computational Linguistics (Volume 1: Long Papers), 13369–85.