In this exercise, we will replicate the study by O’Campo-Roland. The article’s research question guiding the conjoint design is whether and how white and Black Americans differ in their perceptions of which Latinos are considered “American.” The design systematically varies Latino characteristics such as phenotype, immigrant background/legal status, language, socioeconomic markers, religion, and political affiliation. The goal is to uncover how prototypical (white) versus peripheral (Black) group members draw national boundaries of inclusion, and which Latino subgroups are deemed part of the American imagined community.
The study employs a paired-profile conjoint survey experiment to assess perceptions of Latinos’ Americanness. A sample of 750 white and 750 Black respondents (total N=1,500) was recruited through YouGov. Each respondent evaluated ten Latino profiles, presented in five side-by-side tasks, and for each task was asked (1) to choose which profile they thought was “more American” and (2) to rate each profile on a 1–7 Americanness scale.
The profiles were randomly generated by varying a set of attributes that capture Latino heterogeneity, including:
Physical appearance (photos from the Chicago Face Database spanning skin tones and genders);
Immigrant background/legal status (undocumented, legal, naturalized, or U.S.-born descendants of legal/undocumented immigrants);
Language ability (only English, bilingual, limited English, no English);
Socioeconomic characteristics (education and occupation levels);
Religion (Catholic, Evangelical, Presbyterian, not religious);
Political affiliation (Democrat, Republican, Independent, non-political);
Spousal background (American, white, Black, same as profile)
Design restrictions prevented unrealistic combinations (e.g., inconsistent education and occupation pairings). Analytically, the study estimated Average Marginal Component Effects (AMCEs) across all respondents, then compared marginal mean differences and attribute salience between white and Black respondents, as well as variation within groups by strength of American or racial identity. We will replicate the article findings on the main analysis.
###SET WORKING DIRECTORY and LOAD FILES ----onedrive_url <-"https://1drv.ms/x/c/0f7d0a7f95ac8880/Edv5Acp5lARJicU-cxAi6q0B9Zn36gXoE4Syl_gv-8MCLw?e=x3jCEe&download=1"#full <- read.csv(url(onedrive_url))full <-read.csv('C:/Users/jmcar/OneDrive/Documentos/JOAO/UNC/2025 Fall/Advanced Causal/Class 1/Replication Material OCampo 2025/b_data/1_raw_data_for_long.csv')##### Recoding key analytic variables----full <- full %>%mutate(#Race of respondentrace =case_when(race ==1~'White respondent', race ==2~'Black respondent'),race =factor(race, levels =c("White respondent", "Black respondent")),#American identity importanceamerimport =case_when(Q7_2 ==1~1, Q7_2 ==2~2, Q7_2 ==3~3, Q7_2 ==4~4),#Racial identity importanceraceimport =case_when(Q7_3 ==1~1, Q7_3 ==2~2, Q7_3 ==3~3, Q7_3 ==4~4),#Perceived prototypicalityprototypical =case_when(Q7_4 ==1~1, Q7_4 ==2~2, Q7_4 ==3~3, Q7_4 ==4~4))###Splitting identity perception variables into two and recoding the variables into high and low ----full$amerimport_high <-quantcut(full$amerimport, q=2)full$raceimport_high <-quantcut(full$raceimport, q=2)full$prototypical_high <-quantcut(full$prototypical, q=2)full <- full %>%mutate(amerimport_high =case_when(amerimport_high =="[1,3]"~'Low', amerimport_high =="(3,4]"~'High'),raceimport_high =case_when(raceimport_high =="[1,3]"~'Low', raceimport_high =="(3,4]"~'High'),prototypical_high =case_when(prototypical_high =="[1,3]"~'Low', prototypical_high =="(3,4]"~'High'))
1.3 Reshaping Data
In order to perform the conjoint analysis, the data frame must be in a long format, which means that each row will contain a task, instead of a respondent itself. The function cj_tidy from the package cregg can help with it. We just need to specify a list containing the characteristics of each task and a list with the outcome.
After reshaping the data set, we will recode the categories of each group in meaningfull terms, transforming the numerical codes into actual categories.
Show Answer
# Recoding profile characteristics as factorslong <- long %>%mutate(# Ensure numeric codes (or character across-the-board)across(c(Faces, Background, Identifies, Language, Education, Profession, Religion, Political, Spouse),~as.integer(.x)),Faces =factor(recode(Faces,`1`="White man", `2`="White woman", `3`="Light man", `4`="Light woman",`5`="Medium man", `6`="Medium woman", `7`="Brown man", `8`="Brown woman",`9`="Black man", `10`="Black woman",.default =NA_character_ ), levels =c("White man","White woman","Light man","Light woman","Medium man","Medium woman","Brown man","Brown woman","Black man","Black woman"), ordered =TRUE),Background =factor(recode(Background,`1`="Legal immigrant", `2`="Undoc. immigrant", `3`="Naturalized citizen",`4`="US-born legal parents", `5`="US-born undoc. parents",`6`="US-born legal grandparents", `7`="US-born undoc. grandparents",.default =NA_character_ ), levels =c("Legal immigrant","Undoc. immigrant","Naturalized citizen","US-born legal parents","US-born undoc. parents","US-born legal grandparents","US-born undoc. grandparents")),Identifies =factor(recode(Identifies,`1`="American", `2`="Latino", `3`="Hispanic", `4`="Mexican-American",`5`="Mexican", `6`="White", `7`="Black", .default =NA_character_ ), levels =c("American","Latino","Hispanic","Mexican-American","Mexican","White","Black")),Language =factor(recode(Language,`1`="Only English", `2`="Bilingual", `3`="Limited English", `4`="No English",.default =NA_character_ ), levels =c("Only English","Bilingual","Limited English","No English"),ordered =TRUE),Education =factor(recode(Education,`1`="High school dropout", `2`="High school graduate",`3`="Bachelor's degree", `4`="Advanced/graduate degree",.default =NA_character_ ), levels =c("High school dropout","High school graduate","Bachelor's degree","Advanced/graduate degree"),ordered =TRUE),Profession =factor(recode(Profession,`1`="Waiter", `2`="Janitor", `3`="Sales manager", `4`="Teacher",`5`="IT professional", `6`="Doctor", `7`="Small business owner",.default =NA_character_ ), levels =c("Waiter","Janitor","Sales manager","Teacher","IT professional","Doctor","Small business owner")),Religion =factor(recode(Religion,`1`="Presbyterian", `2`="Evangelical", `3`="Catholic", `4`="Not religious",.default =NA_character_ ), levels =c("Presbyterian","Evangelical","Catholic","Not religious")),Political =factor(recode(Political,`1`="Democrat", `2`="Republican", `3`="Independent", `4`="Not political",.default =NA_character_ ), levels =c("Democrat","Republican","Independent","Not political")),Spouse =factor(recode(Spouse,`1`="Not married", `2`="S. is American", `3`="S. is Black",`4`="S. is White", `5`="S. is same as profile",.default =NA_character_ ), levels =c("Not married","S. is American","S. is Black","S. is White","S. is same as profile")) )# cleaning American rating variabledf <- long %>%mutate(rating =case_when(rating ==1~1, rating ==2~2, rating ==3~3, rating ==4~4, rating ==5~5, rating ==6~6, rating ==7~7))df$rating_r <-rescale(df$rating) #rescales American ratings from 0 to 1tab_df(df |>slice_head(n=10))
X
caseid
weight
race
educ
gender
employ
faminc_new
religpew
birthyr
ideo5
pid7
presvote16post
votereg
Q7_2
Q7_3
Q7_4
Q4_3
Q4_5_2
amerimport
raceimport
prototypical
amerimport_high
raceimport_high
prototypical_high
task
profile
Faces
Background
Identifies
Language
Education
Profession
Religion
Political
Spouse
rating
choice
pair
rating_r
1.10
1203595341
1.55
White respondent
5
1
1
6
1
1963
4
6
2
1
3
2
3
1
1
3
2
3
Low
Low
Low
1
A
Brown woman
Undoc. immigrant
Hispanic
Limited English
High school dropout
Waiter
Presbyterian
Not political
S. is same as profile
2
2
1
0.17
2.10
1204107895
1.03
White respondent
2
2
7
1
1
1988
6
8
7
2
1
1
2
1
1
1
1
2
Low
Low
Low
1
A
Medium man
Undoc. immigrant
Hispanic
Bilingual
Bachelor's degree
Janitor
Presbyterian
Independent
Not married
5
1
2
0.67
3.10
1204107941
0.76
White respondent
1
1
6
6
1
1953
6
5
7
2
4
4
4
1
1
4
4
4
High
High
High
1
A
Medium woman
US-born legal parents
American
Only English
Bachelor's degree
Small business owner
Presbyterian
Republican
S. is same as profile
5
1
3
0.67
4.10
1204110451
0.90
White respondent
3
2
1
4
9
1977
2
3
1
1
2
2
3
1
1
2
2
3
Low
Low
Low
1
A
Brown man
US-born legal parents
Mexican
Only English
High school dropout
Sales manager
Not religious
Independent
S. is Black
7
1
4
1.00
5.10
1204116055
0.72
White respondent
6
1
8
6
1
1994
3
4
5
1
2
2
3
1
1
2
2
3
Low
Low
Low
1
A
Brown woman
US-born undoc. grandparents
Mexican-American
Only English
High school graduate
Janitor
Presbyterian
Independent
S. is same as profile
7
1
5
1.00
6.10
1204116247
1.17
White respondent
2
1
1
13
11
1966
4
7
2
1
2
1
4
1
1
2
1
4
Low
Low
High
1
A
Black man
Undoc. immigrant
American
Bilingual
Bachelor's degree
Sales manager
Evangelical
Republican
Not married
2
2
6
0.17
7.10
1204116147
0.79
White respondent
2
2
5
2
11
1955
2
4
7
2
4
4
4
1
1
4
4
4
High
High
High
1
A
Medium man
US-born legal parents
Mexican-American
Only English
Advanced/graduate degree
Janitor
Not religious
Not political
S. is American
2
1
7
0.17
8.10
1204116213
1.41
White respondent
4
1
1
4
2
1969
5
7
2
1
4
2
1
1
1
4
2
1
High
Low
Low
1
A
White woman
US-born legal parents
American
Limited English
Bachelor's degree
Teacher
Evangelical
Not political
S. is Black
6
1
8
0.83
9.10
1204117027
1.03
White respondent
4
2
6
1
9
1958
1
1
7
1
4
2
3
1
1
4
2
3
High
Low
Low
1
A
Light woman
US-born undoc. grandparents
White
Limited English
Advanced/graduate degree
Teacher
Presbyterian
Independent
S. is same as profile
7
2
9
1.00
10.10
1204116383
0.98
White respondent
3
1
5
2
2
1948
3
4
7
1
4
4
4
1
1
4
4
4
High
High
High
1
A
White woman
Naturalized citizen
American
No English
High school dropout
Janitor
Evangelical
Independent
Not married
6
1
10
0.83
To end, we will transform the data again so the factor categories are well defined within the conjoint desing. It is important to notice that, due to a package bug, we need to repeat this process exporting the previous file and downloading it back again.
Accounting for a simple conjoint design, the model can be identified with a simple OLS regression with clustered standard errors by respondent. We can easily estimate this using the lm_robust method from the estimatr package. We just need to specify the equation, the clusters and the weights within it.
However, we can incorporate more characteristics of the design by using specific packages. For instance, we can run the function amce from the package cjoint to specify design restrictions, such as impossible combinations and a relative probability of each category to be presented.
Show Answer
###CONJOINT DESIGN ----# Providing a list with all the attributes available by each featureattribute_list <-list()attribute_list[["Faces"]] <-c("White man", "White woman", "Light man", "Light woman","Medium man", "Medium woman", "Brown man", "Brown woman","Black man", "Black woman")attribute_list[["Background"]] <-c("Legal immigrant", "Undoc. immigrant","Naturalized citizen", "US-born legal parents","US-born undoc. parents","US-born legal grandparents","US-born undoc. grandparents")attribute_list[["Identifies"]] <-c("American", "Latino","Hispanic", "Mexican-American","Mexican", "White", "Black")attribute_list[["Language"]] <-c("Only English","Bilingual","Limited English","No English")attribute_list[["Education"]] <-c("High school dropout","High school graduate","Bachelor's degree","Advanced/graduate degree")attribute_list[["Profession"]] <-c("Waiter", "Janitor","Sales manager", "Teacher","IT professional", "Doctor","Small business owner")attribute_list[["Religion"]] <-c("Presbyterian", "Evangelical","Catholic", "Not religious")attribute_list[["Political"]] <-c("Democrat", "Republican","Independent", "Not political")attribute_list[["Spouse"]] <-c("Not married", "S. is American","S. is Black", "S. is White","S. is same as profile")# Providing a list with all the impossible attributes to be combined # (example a doctor that don't have highschool)constraint_list <-list()constraint_list[[1]] <-list()constraint_list[[1]][["Education"]] <-c("High school dropout","High school graduate")constraint_list[[1]][["Profession"]] <-c("Doctor","IT professional", "Teacher")constraint_list[[2]] <-list()constraint_list[[2]][["Education"]] <-c("Bachelor's degree")constraint_list[[2]][["Profession"]] <-c("Doctor")constraint_list[[3]] <-list()constraint_list[[3]][["Background"]] <-c("US-born legal parents","US-born undoc. parents","US-born legal grandparents","US-born undoc. grandparents")constraint_list[[3]][["Language"]] <-c("No English")constraint_list[[4]] <-list()constraint_list[[4]][["Background"]] <-c("Legal immigrant","Naturalized citizen","Undoc. immigrant")constraint_list[[4]][["Language"]] <-c("Only English")constraint_list[[5]] <-list()constraint_list[[5]][["Profession"]] <-c("IT professional","Doctor","Sales manager","Teacher")constraint_list[[5]][["Language"]] <-c("No English")constraint_list[[6]] <-list()constraint_list[[6]][["Faces"]] <-c("White man", "White woman", "Light man", "Light woman","Medium man", "Medium woman")constraint_list[[6]][["Identifies"]] <-c("Black")constraint_list[[7]] <-list()constraint_list[[7]][["Faces"]] <-c("Brown man", "Brown woman","Black man", "Black woman")constraint_list[[7]][["Identifies"]] <-c("White")# To end, we need to provide a list with the marginal_weights <-list()marginal_weights[["Faces"]] <-rep(1/length(attribute_list[["Faces"]]),length(attribute_list[["Faces"]]))marginal_weights[["Background"]] <-rep(1/length(attribute_list[["Background"]]),length(attribute_list[["Background"]]))marginal_weights[["Identifies"]] <-rep(1/length(attribute_list[["Identifies"]]),length(attribute_list[["Identifies"]]))marginal_weights[["Language"]] <-rep(1/length(attribute_list[["Language"]]),length(attribute_list[["Language"]]))marginal_weights[["Education"]] <-rep(1/length(attribute_list[["Education"]]),length(attribute_list[["Education"]]))marginal_weights[["Profession"]] <-rep(1/length(attribute_list[["Profession"]]),length(attribute_list[["Profession"]]))marginal_weights[["Religion"]] <-rep(1/length(attribute_list[["Religion"]]),length(attribute_list[["Religion"]]))marginal_weights[["Political"]] <-c(2/9, 2/9, 2/9, 3/9)marginal_weights[["Spouse"]] <-c(5/15, 3/15, 2/15, 2/15, 3/15)conjointdesign <- cjoint::makeDesign(type='constraints', attribute.levels=attribute_list,constraints=constraint_list, level.probs=marginal_weights)baselines <-list()baselines$Education <-"High school graduate"baselines$Background <-"US-born legal grandparents"baselines$Profession <-"Teacher"baselines$Political <-"Not political"baselines$Religion <-"Not religious"#### AMCE of Perceptions of Americanness (Amerian rating) ----####NOTE: This model is computationally intensive and may not run on all computersratingamce_r <- cjoint::amce(rating_r ~ Faces + Background + Identifies + Language + Education + Profession + Religion + Political + Spouse, data=df, cluster=TRUE, respondent.id="caseid", design=conjointdesign,weights="weight", baselines=baselines,na.ignore=TRUE)### Creating a table to visualize the resultssum_amce_r <-summary(ratingamce_r)amce_r <-sum_amce_r$amceamcer_table <- amce_r[c(2:6)]tab_df(amcer_table)
Level
Estimate
Std..Err
z.value
Pr...z..
Legal immigrant
-0.04
0.01
-2.96
0.00
Undoc. immigrant
-0.21
0.02
-13.67
0.00
Naturalized citizen
-0.02
0.01
-1.35
0.18
US-born legal parents
0.02
0.01
2.19
0.03
US-born undoc. parents
-0.05
0.01
-4.10
0.00
US-born undoc. grandparents
-0.02
0.01
-2.46
0.01
High school dropout
-0.00
0.01
-0.40
0.69
Bachelor's degree
0.01
0.01
0.95
0.34
Advanced/graduate degree
0.01
0.01
0.67
0.51
White woman
-0.01
0.01
-0.91
0.36
Light man
-0.00
0.01
-0.22
0.83
Light woman
-0.01
0.01
-0.82
0.41
Medium man
-0.01
0.01
-0.79
0.43
Medium woman
-0.01
0.01
-0.77
0.44
Brown man
-0.03
0.01
-2.41
0.02
Brown woman
-0.01
0.01
-1.09
0.28
Black man
-0.00
0.01
-0.34
0.74
Black woman
0.01
0.01
0.62
0.53
Latino
-0.02
0.01
-2.03
0.04
Hispanic
-0.02
0.01
-2.57
0.01
Mexican-American
-0.02
0.01
-1.78
0.07
Mexican
-0.03
0.01
-2.80
0.01
White
-0.01
0.01
-0.98
0.33
Black
0.00
0.01
0.15
0.88
Bilingual
0.01
0.01
0.56
0.58
Limited English
-0.02
0.01
-2.03
0.04
No English
-0.04
0.04
-1.01
0.31
Democrat
0.01
0.01
1.17
0.24
Republican
0.00
0.01
0.46
0.65
Independent
0.01
0.01
2.15
0.03
Waiter
-0.00
0.02
-0.12
0.91
Janitor
0.01
0.01
0.58
0.56
Sales manager
0.00
0.01
0.15
0.88
IT professional
0.01
0.01
0.80
0.43
Doctor
0.01
0.02
0.35
0.73
Small business owner
0.02
0.01
1.59
0.11
Presbyterian
0.00
0.01
0.07
0.95
Evangelical
-0.00
0.01
-0.38
0.70
Catholic
0.00
0.01
0.61
0.54
S. is American
0.00
0.01
0.71
0.48
S. is Black
-0.01
0.01
-0.68
0.49
S. is White
-0.01
0.01
-0.75
0.45
S. is same as profile
-0.00
0.01
-0.69
0.49
1.6 Visualizations
Now let’s visualize the results on a figure based on the plot method. In order to do so, we will use a a combination of the method plot, implemented in cjoint with the ggplot in order to make the graph more presentable.
Show Answer
# Figure Limitslim <-c(-.25, .05)# Feature order c_order <-c("Faces", "Identifies", "Religion", "Background", "Language","Spouse", "Education", "Profession", "Political")figure_1 <-plot(ratingamce_r, main ="Average Marginal Component Effect of Perceived Americanness Among All Respondents",xlab ="Change: American Rating (0 'not at all American' - 1 'very much American')", group.order= c_order,colors="black",xlim=lim,point.size=0.4, dodge.size=1,plot.theme = (ggplot2::theme_bw() +theme(legend.position="none", plot.title=element_text(size=10))))
1.7 Extra features
The cregg package also allow us to perform the conjoint in a comparative way, seeing how different groups within the sample using the function mm_diffs. We again need to specify the design and add the argument by, which will specify the respondent groups that we are comparing.
Show Answer
###Marginal mean differences in perceptions of Americanness by race model----american_diff <- cregg::mm_diffs(na.omit(df), rating_r ~ Faces + Background+ Education + Profession+ Language + Political+ Religion + Spouse+ Identifies,by =~ race,id=~caseid,weights =~weight, feature_order = c_order)american_diff_table <- american_diff[c(5:9)]tab_df(american_diff_table)
level
estimate
std.error
z
p
White man
0.05
0.02
2.38
0.02
White woman
0.05
0.02
2.72
0.01
Light man
0.02
0.02
0.96
0.33
Light woman
0.05
0.02
2.65
0.01
Medium man
0.05
0.02
2.73
0.01
Medium woman
0.06
0.02
3.31
0.00
Brown man
0.04
0.02
1.90
0.06
Brown woman
0.03
0.02
1.36
0.17
Black man
0.03
0.02
1.86
0.06
Black woman
0.02
0.02
1.21
0.23
American
0.04
0.02
2.28
0.02
Latino
0.05
0.02
2.99
0.00
Hispanic
0.03
0.02
2.06
0.04
Mexican-American
0.03
0.02
2.10
0.04
Mexican
0.02
0.02
1.53
0.13
White
0.08
0.02
4.52
0.00
Black
0.03
0.02
1.26
0.21
Presbyterian
0.05
0.01
3.34
0.00
Evangelical
0.03
0.01
2.34
0.02
Catholic
0.03
0.01
2.12
0.03
Not religious
0.05
0.01
3.32
0.00
Legal immigrant
0.07
0.02
3.92
0.00
Undoc. immigrant
-0.07
0.02
-3.22
0.00
Naturalized citizen
0.07
0.02
3.80
0.00
US-born legal parents
0.07
0.01
4.50
0.00
US-born undoc. parents
0.00
0.02
0.14
0.89
US-born legal grandparents
0.07
0.02
4.47
0.00
US-born undoc. grandparents
0.04
0.02
2.73
0.01
Only English
0.06
0.01
3.93
0.00
Bilingual
0.04
0.01
3.55
0.00
Limited English
0.03
0.01
1.94
0.05
No English
0.03
0.02
1.10
0.27
Not married
0.05
0.01
3.48
0.00
S. is American
0.03
0.01
1.96
0.05
S. is Black
0.04
0.02
2.31
0.02
S. is White
0.05
0.02
3.25
0.00
S. is same as profile
0.03
0.01
1.83
0.07
High school dropout
0.03
0.02
1.86
0.06
High school graduate
0.04
0.02
2.44
0.01
Bachelor's degree
0.04
0.01
3.04
0.00
Advanced/graduate degree
0.05
0.01
3.36
0.00
Waiter
0.02
0.02
1.30
0.19
Janitor
0.05
0.02
2.89
0.00
Sales manager
0.05
0.02
2.88
0.00
Teacher
0.04
0.02
1.90
0.06
IT professional
0.05
0.02
2.37
0.02
Doctor
0.08
0.03
3.02
0.00
Small business owner
0.04
0.01
2.48
0.01
Democrat
0.03
0.01
1.95
0.05
Republican
0.05
0.01
3.59
0.00
Independent
0.04
0.01
2.56
0.01
Not political
0.04
0.01
2.88
0.00
To end, let`s visualize those differences.
Show Answer
american_diff_p <-plot(american_diff)figure_2 <- american_diff_p + ggplot2::theme_bw() +theme(legend.position="none", plot.title=element_text(size=10)) +scale_color_manual(values =rep("black", 9)) +geom_point(size =2) + ggplot2::labs(x ="Estimated Difference Between White and Black Respondents",title ="Marginal Mean Differences in Perceived Americanness Between White and Black Respondents") figure_2