library(tidyverse)
library(gridExtra)
library(readxl)
library(ggthemes)
library(knitr)
library(kableExtra)
library(xtable)
library(texreg)
library(broom)
library(lme4)Welfare in Experimental News Markets
Data Description and Analysis
The follow analysis is implemented in R [version 4.1.1 (2021-08-10) – “Kick Things”]
1 Dataset
- These are the choice data
- These are the questionnaire data
- These are the time on page data
- Load the datasets
# Main data source: choices
d <- read_csv("./CHOICES.csv") %>%
mutate(Correct_C=ifelse(State==Choice_C,"Correct","Wrong")) %>%
mutate(Payoff=ifelse(Type=="A",
ifelse(Choice_C=="black",1200,400),
ifelse(Type=="B",ifelse(Choice_C=="red",1200,400),
ifelse(Correct_C=="Correct",600,200)))) %>%
mutate(Cost=ifelse(Type=="A",abs(Drawn-Report_A)*25/3,ifelse(Type=="B",abs(Drawn-Report_B)*25/3,0))) %>%
mutate(Net_payoff=(Payoff-Cost)) %>%
mutate(Net_payoff=ifelse((Treatment=="Monopoly" & Type=="B"),Payoff,Net_payoff))
# Questionnaire data
d.q <- read_csv("./QUESTIONNAIRE.csv")
# Time on page data
d.t <- read_csv("./TIMES.csv") %>% arrange(session_code,participant_code,epoch_time) %>%
rename(participant.code=participant_code) %>% arrange(participant.code, round_number)1.1 Main variables
- Treatment: treatment identifier
- Competition = COMP; Monopoly=MONO
- session.code: session unique identifier
- participant.code: participant’s unique identifier
- Type: role
- A = \(Sender_1\)
- B = \(Sender_2\)
- C = \(DM\)
- Group: match identifier in session and round
- Round: Round identifier (1–30)
- Drawn: randomly drawn number (\(drawn\))
- \(\{-100, ... 100\}\)
- Report_A: number reported by \(Sender_1\)
- \(\{-100, ... 100\}\)
- Report_B: number reported by \(Sender_2\)
- \(\{-100, ... 100\}\)
- Choice_C: state chosen by
- \(\{Red, Black\}\)
- State : actual state
- \(\{Red, Black\}\)
- Bel_A1: the probability that Player A is going to report the value truthfully
- 1: 0%-20%; 2:21%-40%; 3:41%-60%; 4:61%-80%; 5:81%-100%<
- 1: 0%-20%; 2:21%-40%; 3:41%-60%; 4:61%-80%; 5:81%-100%<
- Bel_A2: the probability that Player C is going to choose Black
- 1: 0%-20%; 2:21%-40%; 3:41%-60%; 4:61%-80%; 5:81%-100%<
- Payoff: Earnings from the choice
- Cost: Cost of signal
- Net_payoff: Earnings from the choice - Cost of signal
- Correct_C: whether the \(DM\) choiceis correct
- \(\{Correct, Wrong\}\)
2 Sample descriptives
- Number of sessions:
n 7 - Number of sessions by treatment:
Treatment n Competition 3 Monopoly 4
- Number of sessions by treatment:
- Number of participants:
n 192 - Number of participants by role
Type n A 64 B 64 C 64 - Number of participants by treatment
Treatment n Competition 96 Monopoly 96 - Number of participants by treatment and role:
Treatment Type n Competition A 32 Competition B 32 Competition C 32 Monopoly A 32 Monopoly B 32 Monopoly C 32
- Number of participants by role
3 Senders
3.1 Figure 1: Drawn and reported values by treatment.
3.1.1 MONO
marginal<- d %>% filter(Treatment=="Monopoly") %>%
gather("Type","Value",8:8) %>%
group_by(Type, Drawn) %>%
count(Value) %>%
mutate(Type=ifelse(Type=="Report_A","Sender 1","Sender 2")) %>%
mutate(Freq=-99)
d %>% filter(Treatment=="Monopoly") %>%
gather("Type","Value",8:8) %>%
group_by(Type, Drawn) %>%
count(Value) %>%
mutate(Type=ifelse(Type=="Report_A","Sender 1","Sender 2")) %>%
mutate(Freq=prop.table(n)) %>%
ggplot(aes(x = Drawn, y = Value, size=Freq))+#
geom_abline(intercept=0,slope=1,linetype=2)+
geom_hline(yintercept=0,linetype=2)+
geom_vline(xintercept=0,linetype=2)+
geom_jitter(pch=21,alpha=.5,color="black",fill="slategray")+
geom_smooth(color="red")+
geom_rug(data=marginal,col="black",alpha=0.1, size=1)+
theme_bw()+
scale_x_continuous(limits=c(-102,102))+
scale_y_continuous(limits=c(-102,102))+
scale_fill_gradient(low="slategray1",high="slategray")+
scale_size(guide = "none")+
facet_wrap(.~Type)+
theme_bw()+ # the theme
labs(
y = "Reported Value",
x= "Drawn Value",
fill="Freq", color="Freq",size= "Subject")+ # labels
theme(legend.position="none",
axis.text=element_text(size=8),
axis.title=element_text(size=14,face="bold"),
strip.text.x = element_text(size = 14)) #axisggsave("MONO_report.png",width=6, height=5,dpi=300)3.1.2 COMP
marginal<- d %>% filter(Treatment=="Competition" & (Type=="C")) %>%
select(Drawn,Report_A,Report_B) %>%
gather("Type","Value",2:3) %>%
group_by(Type) %>%
mutate(Freq=-99)%>%
mutate(Type=ifelse(Type=="Report_A","Sender 1","Sender 2"))
g <-
d %>% filter(Treatment=="Competition" & (Type=="C")) %>%
gather("Type","Value",8:9) %>%
group_by(Type, Drawn) %>%
count(Value) %>%
mutate(Freq=prop.table(n)) %>%
mutate(Type=ifelse(Type=="Report_A","Sender 1","Sender 2")) %>%
ggplot(aes(x = Drawn, y = Value, fill = Freq, size=Freq))+
geom_abline(intercept=0,slope=1,linetype=2)+
geom_hline(yintercept=0,linetype=2)+
geom_vline(xintercept=0,linetype=2)+
geom_point(pch=21,alpha=.5,color="black")+
geom_smooth(color="red")+
geom_rug(data=marginal,col="black",alpha=0.1, size=1)+
theme_bw()+
scale_x_continuous(limits=c(-102,102))+
scale_y_continuous(limits=c(-102,102))+
scale_fill_gradient(low="slategray1",high="slategray")+
scale_size(guide = "none")+
facet_wrap(.~Type, ncol=1)+
theme_bw()+
labs(
y = "Reported Value",
x= "Drawn Value",
fill="Freq", color="Freq",size= "Subject")+
theme(legend.position="none",
axis.text=element_text(size=8),
axis.title=element_text(size=14,face="bold"),
strip.text.x = element_text(size = 14)
) #axis
# Only Type 1
d %>% filter(Treatment=="Competition" & (Type=="C")) %>%
gather("Type","Value",8:9) %>%
group_by(Type, Drawn) %>%
count(Value) %>%
mutate(Freq=prop.table(n)) %>%
mutate(Type=ifelse(Type=="Report_A","Sender 1","Sender 2")) %>%
filter(Type=="Sender 1") |>
mutate(Type2="Sender 1") |>
ggplot(aes(x = Drawn, y = Value, size=Freq))+
geom_abline(intercept=0,slope=1,linetype=2)+
geom_hline(yintercept=0,linetype=2)+
geom_vline(xintercept=0,linetype=2)+
geom_point(pch=21,alpha=.5,color="black",fill="slategray")+
geom_smooth(color="red")+
geom_rug(data=marginal |> filter(Type=="Sender 1"),col="black",alpha=0.1, size=1)+
theme_bw()+
scale_x_continuous(limits=c(-102,102))+
scale_y_continuous(limits=c(-102,102))+
scale_fill_gradient(low="slategray1",high="slategray")+
scale_size(guide = "none")+
facet_wrap(.~Type2, ncol=1)+
theme_bw()+
labs(
y = "Reported Value",
x= "Drawn Value",
fill="Freq", color="Freq",size= "Subject")+
theme(legend.position="none",
axis.text=element_text(size=8),
axis.title=element_text(size=14,face="bold"),
strip.text.x = element_text(size = 14)
) #axisggsave("COMP_report_1.png",width=6, height=5,dpi=300)
## Only Type 2
d %>% filter(Treatment=="Competition" & (Type=="C")) %>%
gather("Type","Value",8:9) %>%
group_by(Type, Drawn) %>%
count(Value) %>%
mutate(Freq=prop.table(n)) %>%
mutate(Type=ifelse(Type=="Report_A","Sender 1","Sender 2")) %>%
filter(Type=="Sender 2") |>
mutate(Type2="Sender 2") |>
ggplot(aes(x = Drawn, y = Value, size=Freq))+
geom_abline(intercept=0,slope=1,linetype=2)+
geom_hline(yintercept=0,linetype=2)+
geom_vline(xintercept=0,linetype=2)+
geom_point(pch=21,alpha=.5,color="black",fill="slategray")+
geom_smooth(color="red")+
geom_rug(data=marginal |> filter(Type=="Sender 2"),col="black",alpha=0.1, size=1)+
theme_bw()+
scale_x_continuous(limits=c(-102,102))+
scale_y_continuous(limits=c(-102,102))+
scale_fill_gradient(low="slategray1",high="slategray")+
scale_size(guide = "none")+
facet_wrap(.~Type2, ncol=1)+
theme_bw()+
labs(
y = "Reported Value",
x= "Drawn Value",
fill="Freq", color="Freq",size= "Subject")+
theme(legend.position="none",
axis.text=element_text(size=8),
axis.title=element_text(size=14,face="bold"),
strip.text.x = element_text(size = 14)
) #axisggsave("COMP_report_2.png",width=6, height=5,dpi=300)3.2 Descriptives
- Truth telling
d %>% select(participant.code,Treatment,Type,Drawn, Report_A, Report_B) %>%
mutate(truth_telling=ifelse(Type=="A",ifelse(Drawn == Report_A,1,0), ifelse(Type=="B",ifelse(Drawn == Report_B,1,0),NA))) %>%
select(participant.code, Treatment, Type, truth_telling) %>%
filter(Type=="A" | Type=="B") %>%
group_by(Treatment) %>%
count(truth_telling) %>%
na.omit() %>%
mutate(Freq=prop.table(n)) %>%
kable() %>% kable_minimal()| Treatment | truth_telling | n | Freq |
|---|---|---|---|
| Competition | 0 | 975 | 0.5078125 |
| Competition | 1 | 945 | 0.4921875 |
| Monopoly | 0 | 418 | 0.4354167 |
| Monopoly | 1 | 542 | 0.5645833 |
- Deviation from true value
d %>% select(participant.code,Treatment,Type,Drawn, Report_A, Report_B) %>%
gather("Key","Value",5:6) %>%
mutate(Dist=ifelse(Key=="Report_A",(Value-Drawn),Drawn-Value)) %>%
filter((Type=="A" & Key=="Report_A") | (Type=="B" & Key=="Report_B")) %>%
group_by(participant.code,Treatment) %>%
summarise_at("Dist",mean) %>%
group_by(Treatment) %>%
summarize_at("Dist",list(N=~n(),Mean=~mean(.,na.rm=TRUE), SD=~sd(.,na.rm=TRUE), Median=~median(.,na.rm=TRUE))) %>%
kable() %>% kable_minimal()| Treatment | N | Mean | SD | Median |
|---|---|---|---|---|
| Competition | 64 | 9.614062 | 9.904676 | 7.216667 |
| Monopoly | 64 | 9.634375 | 10.975948 | 6.700000 |
- Deviation from true value when drawn is adverse
d %>% select(participant.code,Treatment,Type,Drawn, Report_A, Report_B) %>%
gather("Key","Value",5:6) %>%
mutate(Dist=ifelse(Key=="Report_A",(Value-Drawn),Drawn-Value)) %>%
filter((Type=="A" & Key=="Report_A") | (Type=="B" & Key=="Report_B")) %>%
filter((Type=="A" & Drawn<0) | (Type=="B" & Drawn>0)) %>%
group_by(participant.code,Treatment) %>%
summarise_at("Dist",mean) %>%
group_by(Treatment) %>%
summarize_at("Dist",list(N=~n(),Mean=~mean(.,na.rm=TRUE), SD=~sd(.,na.rm=TRUE), Median=~median(.,na.rm=TRUE))) %>%
kable() %>% kable_minimal()| Treatment | N | Mean | SD | Median |
|---|---|---|---|---|
| Competition | 64 | 13.38616 | 11.78028 | 10.33333 |
| Monopoly | 64 | 13.29056 | 14.04189 | 10.68125 |
3.3 Table 2: Signal Costs (individual observations).
- Monopoly (average at individual level)
d %>% filter(Treatment=="Monopoly" & Type=="A") %>%
group_by(Type) %>%
summarize_at("Cost",list(N=~n(),Mean=~mean(.), SD=~sd(.), Median=~median(.))) %>%
kable() %>% kable_minimal()| Type | N | Mean | SD | Median |
|---|---|---|---|---|
| A | 960 | 85.85938 | 134.6635 | 0 |
- Competition (average at individual level)
d %>% filter(Treatment=="Competition" & (Type=="A"| Type=="B")) %>%
group_by(Type) %>%
summarize_at("Cost",list(N=~n(),Mean=~mean(.), SD=~sd(.), Median=~median(.))) %>%
kable() %>% kable_minimal()| Type | N | Mean | SD | Median |
|---|---|---|---|---|
| A | 960 | 88.53299 | 127.3724 | 16.66667 |
| B | 960 | 93.09028 | 145.9500 | 0.00000 |
- Tests
- Take average at the individual level
d |> group_by(participant.code, Type, Treatment) %>%
summarize_at("Cost",mean) -> dt
wilcox.test(
dt |> filter(Treatment=="Competition" & Type=="A") |> pull(Cost),
dt |> filter(Treatment=="Monopoly" & Type=="A") |> pull(Cost),
) |> tidy() |> kable() %>% kable_minimal()| statistic | p.value | method | alternative |
|---|---|---|---|
| 577 | 0.3863423 | Wilcoxon rank sum test with continuity correction | two.sided |
wilcox.test(
dt |> filter(Treatment=="Competition" & Type=="B") |> pull(Cost),
dt |> filter(Treatment=="Competition" & Type=="A") |> pull(Cost),
) |> tidy() |> kable() %>% kable_minimal()| statistic | p.value | method | alternative |
|---|---|---|---|
| 482.5 | 0.6969665 | Wilcoxon rank sum test with continuity correction | two.sided |
wilcox.test(
dt |> filter(Treatment=="Competition" & Type=="B") |> pull(Cost),
dt |> filter(Treatment=="Monopoly" & Type=="A") |> pull(Cost),
) |> tidy() |> kable() %>% kable_minimal()| statistic | p.value | method | alternative |
|---|---|---|---|
| 557 | 0.5499899 | Wilcoxon rank sum test with continuity correction | two.sided |
#pull A and B together
wilcox.test(
dt |> filter(Treatment=="Competition" & Type!="C") |> pull(Cost),
dt |> filter(Treatment=="Monopoly" & Type=="A") |> pull(Cost),
) |> tidy() |> kable() %>% kable_minimal()| statistic | p.value | method | alternative |
|---|---|---|---|
| 1134 | 0.3946434 | Wilcoxon rank sum test with continuity correction | two.sided |
#pull A and B together at session elevel
d |> group_by(session.code, Type, Treatment) %>%
summarize_at("Cost",mean) -> dt
wilcox.test(
dt |> filter(Treatment=="Competition" & Type!="C") |> pull(Cost),
dt |> filter(Treatment=="Monopoly" & Type=="A") |> pull(Cost),
) |> tidy() |> kable() %>% kable_minimal() | statistic | p.value | method | alternative |
|---|---|---|---|
| 13 | 0.9142857 | Wilcoxon rank sum exact test | two.sided |
4 Decision Maker
4.1 Figure 2: Decision-makers accuracy by treatment.
4.1.1 COMP
d %>% filter(Treatment=="Competition" & Type=="C") %>%
select(Treatment, session.code, Group, Round, Drawn, Report_A, Report_B, Choice_C, Correct_C) %>%
distinct() |> mutate(AVG_report=(Report_A+Report_B)/2) -> dt.g
marginal<- dt.g %>%
select(Drawn,AVG_report) %>%
mutate(Correct_C=NA) %>% arrange(AVG_report)
ggplot(dt.g ,aes(y = AVG_report, x=Drawn, fill = as_factor(Correct_C)))+
geom_hline(yintercept=0)+
geom_vline(xintercept=0)+
geom_abline(intercept=0,slope=1,linetype=2)+
geom_jitter(alpha=.6,pch=21,size=3)+
# geom_smooth()+
geom_rug(data=marginal,col="black",alpha=0.1, size=1.5)+
scale_x_continuous(limits=c(-102,102))+
scale_y_continuous(limits=c(-102,102))+
#scale_fill_brewer(palette="Paired")+
scale_fill_manual(values=c("white","slategray"))+
scale_size(guide = "none")+
theme_bw()+ # the theme
labs(
# title="Guesses and reported values",
# subtitle="Monopoly",
x = "Drawn",
y= "Average Report",
fill="", color="Subject",size= "Subject")+ # labels
theme(legend.position="bottom",
axis.text=element_text(size=8),
axis.title=element_text(size=14,face="bold"),
legend.text=element_text(size=12)) +
guides(fill = guide_legend(override.aes = list(size=6))) #axis ggsave("COMP_guesses_AVERAGE.png",width=6, height=6,dpi=300) 4.1.2 MONO
marginal<- d %>% filter(Treatment=="Competition" & (Type=="C")) %>%
select(Drawn,Report_A) %>%
mutate(Correct_C=NA)
# DM is better of if RED and DRAWN <=0 AND IF BLACK and DRAWN>=0
d %>% filter(Treatment=="Monopoly" & (Type=="C")) %>%
select(Treatment, session.code, Group, Round, Drawn, Report_A, Correct_C) %>%
distinct() -> dt.g
ggplot(dt.g,aes(y = Report_A, x=Drawn, fill = as_factor(Correct_C)))+
geom_hline(yintercept=0)+
geom_vline(xintercept=0)+
geom_abline(intercept=0,slope=1,linetype=2)+
geom_jitter(alpha=.6,pch=21,size=3)+
# geom_smooth()+
geom_rug(data=marginal,col="black",alpha=0.1, size=1.5)+
scale_x_continuous(limits=c(-102,102))+
scale_y_continuous(limits=c(-102,102))+
#scale_fill_brewer(palette="Paired")+
scale_fill_manual(values=c("white","slategray"))+
scale_size(guide = "none")+
theme_bw()+ # the theme
labs(
# title="Guesses and reported values",
# subtitle="Monopoly",
x = "Drawn",
y= "Report Sender 1",
fill="", color="Subject",size= "Subject")+ # labels
theme(legend.position="bottom",
axis.text=element_text(size=8),
axis.title=element_text(size=14,face="bold"),
legend.text=element_text(size=12)) +
guides(fill = guide_legend(override.aes = list(size=6))) #axis ggsave("MONO_guesses.png",width=6, height=6,dpi=300)
# NEW (but not effective)
# dt.g |>
# count(Correct_C, Report_A, Drawn) %>%
# group_by(Drawn, Report_A) |>
# mutate(Freq=prop.table(n)) %>%
# ggplot(aes(y = Report_A, x=Drawn, fill = as_factor(Correct_C), size=Freq))+
# geom_hline(yintercept=0)+
# geom_vline(xintercept=0)+
# geom_abline(intercept=0,slope=1,linetype=2)+
# geom_point(alpha=.6,pch=21)+
# geom_rug(data=marginal,col="black",alpha=0.1, size=1.5)+
# scale_x_continuous(limits=c(-102,102))+
# scale_y_continuous(limits=c(-102,102))+
# scale_fill_brewer(palette="Okabe-Ito")+
# scale_fill_manual(values=c("white","slategray"))+
# scale_size(guide = "none")+
# theme_bw()+ # the theme
# labs(
# # title="Guesses and reported values",
# # subtitle="Monopoly",
# x = "Drawn",
# y= "Report Sender 1",
# fill="", color="Subject",size= "Subject")+ # labels
# theme(legend.position="bottom",
# axis.text=element_text(size=8),
# axis.title=element_text(size=14,face="bold"),
# legend.text=element_text(size=12)) +
# guides(fill = guide_legend(override.aes = list(size=6))) #axis4.1.3 Descriptives
d %>% group_by(Correct_C, Treatment) %>%
count(Correct_C) %>%
ungroup() %>%
group_by( Treatment) %>%
mutate(Freq=prop.table(n)) %>%
kable() %>% kable_minimal()| Correct_C | Treatment | n | Freq |
|---|---|---|---|
| Correct | Competition | 2130 | 0.7395833 |
| Correct | Monopoly | 2079 | 0.7218750 |
| Wrong | Competition | 750 | 0.2604167 |
| Wrong | Monopoly | 801 | 0.2781250 |
- Monopoly
d %>% filter(Treatment=="Monopoly" & Type=="C") %>%
select(Treatment, session.code, Group, Round, Drawn, Report_A,Drawn, Choice_C, Correct_C) %>%
mutate(Deceitful=ifelse(Report_A>0 & Drawn<0,"Deceit",ifelse(Report_A>0 & Drawn>0,"Honest",NA))) %>% distinct() %>%
group_by(Deceitful) %>%
count(Correct_C) %>%
mutate(Freq=prop.table(n)) %>%
kable() %>% kable_minimal()| Deceitful | Correct_C | n | Freq |
|---|---|---|---|
| Deceit | Correct | 55 | 0.2925532 |
| Deceit | Wrong | 133 | 0.7074468 |
| Honest | Correct | 372 | 0.8322148 |
| Honest | Wrong | 75 | 0.1677852 |
| NA | Correct | 266 | 0.8184615 |
| NA | Wrong | 59 | 0.1815385 |
- Competition
d %>% filter(Treatment=="Competition" & (Type=="C")) %>%
select(Treatment, session.code, Group, Round, Drawn, Report_A, Report_B, Choice_C, Correct_C) %>% mutate(Consistency=ifelse(Report_A*Report_B>0,"Same sign","Opposite signs")) %>% distinct() %>% mutate(Avg_report=(Report_A+Report_B)/2, dist=abs(Report_A-Report_B)) %>%
group_by(Consistency) %>%
count(Correct_C) %>%
mutate(Freq=prop.table(n)) %>%
kable(caption = "Report S1 vs Report S2") %>% kable_minimal()| Consistency | Correct_C | n | Freq |
|---|---|---|---|
| Opposite signs | Correct | 216 | 0.4886878 |
| Opposite signs | Wrong | 226 | 0.5113122 |
| Same sign | Correct | 494 | 0.9536680 |
| Same sign | Wrong | 24 | 0.0463320 |
- Compare average report with drawn value
d %>% filter(Treatment=="Competition" & (Type=="C")) %>%
select(Treatment, session.code, Group, Round, Drawn, Report_A, Report_B, Choice_C, Correct_C) %>% mutate(Avg_report = (Report_A + Report_B) / 2, dist = abs(Report_A - Report_B)) |>
mutate(Consistency=ifelse(Avg_report*Drawn>0,"Same sign","Opposite signs")) %>% distinct() %>% mutate(Avg_report=(Report_A+Report_B)/2, dist=abs(Report_A-Report_B)) %>%
group_by(Consistency) %>%
count(Correct_C) %>%
mutate(Freq=prop.table(n)) %>%
kable(caption="Average report vs drawn value") %>% kable_minimal()| Consistency | Correct_C | n | Freq |
|---|---|---|---|
| Opposite signs | Correct | 87 | 0.3140794 |
| Opposite signs | Wrong | 190 | 0.6859206 |
| Same sign | Correct | 623 | 0.9121523 |
| Same sign | Wrong | 60 | 0.0878477 |
5 Welfare
5.1 Table 3: Net Payoffs (individual observations).
d %>%
group_by(Treatment,Type) %>%
summarise_at("Net_payoff",list(N=~n(),Mean=~mean(.,na.rm=TRUE), Median=~median(.,na.rm=TRUE), SD=~sd(.,na.rm=TRUE)))%>% na.omit() %>%
kable() %>% kable_minimal() | Treatment | Type | N | Mean | Median | SD |
|---|---|---|---|---|---|
| Competition | A | 960 | 738.9670 | 862.5 | 404.1758 |
| Competition | B | 960 | 679.4097 | 400.0 | 397.5772 |
| Competition | C | 960 | 495.8333 | 600.0 | 175.6363 |
| Monopoly | A | 960 | 778.3073 | 900.0 | 386.6147 |
| Monopoly | B | 960 | 735.8333 | 400.0 | 395.0256 |
| Monopoly | C | 960 | 488.7500 | 600.0 | 179.3235 |
d %>% mutate(unique_group=paste(Group,Round,session.code,sep="_")) %>% group_by(Treatment,unique_group) %>% distinct() %>%
summarise_at("Net_payoff",sum) %>%
group_by(Treatment) %>%
summarise_at("Net_payoff",list(N=~n(),Mean=~mean(.,na.rm=TRUE), Median=~median(.,na.rm=TRUE), SD=~sd(.,na.rm=TRUE)))%>% na.omit() %>%
kable() %>% kable_minimal() | Treatment | N | Mean | Median | SD |
|---|---|---|---|---|
| Competition | 960 | 1914.210 | 2033.333 | 310.0672 |
| Monopoly | 960 | 2002.891 | 2191.667 | 263.2047 |
5.2 Table 4: Net Payoffs
d.reg <-
full_join(
d,
d.q %>% select(-Treatment),
by="participant.code"
) %>% mutate(trust_scale=ifelse(trust=="No, bisogna sempre essere prudenti",0,ifelse(trust=="No, spesso bisogna essere prudenti",1,ifelse(trust=="Sì, ti puoi fidare quasi sempre",3,4)))) %>%
mutate(honesty_scale=ifelse(honesty=="No, le persone si comportano quasi sempre in modo corretto",2,ifelse(honesty=="Sì, cercano di approfittarsene quasi sempre",1,0))) %>%
mutate(gender=as_factor(gender)) %>% mutate(gender=factor(gender,levels=c("Femmina","Maschio","Non binario"))) %>%
mutate(Treatment=as_factor(Treatment))
d.reg$Treatment <- factor(d.reg$Treatment, levels=c("Monopoly", "Competition"))#--------------------------------------------------
fit.A <- lmer(Net_payoff ~ Round + as_factor(Treatment)*Drawn+
(gender) + age + risk_taker + (trust_scale ) + (honesty_scale)
+ (1|session.code:participant.code),
data=d.reg %>% filter(Type=="A"), control=lmerControl(optimizer= "bobyqa"))
fit.B <- lmer(Net_payoff ~ Round + as_factor(Treatment)*Drawn+
(gender) + age + risk_taker + (trust_scale ) +(honesty_scale)
+ (1|session.code:participant.code),
data=d.reg %>% filter(Type=="B" & gender!="Non binario"), control=lmerControl(optimizer= "bobyqa"))
fit.C <- lmer(Net_payoff ~ Round + as_factor(Treatment) *abs(Drawn)+
(gender) + age + risk_taker + (trust_scale ) +(honesty_scale)
+(1|session.code:participant.code) ,
data=d.reg %>% filter(Type=="C"), control=lmerControl(optimizer= "bobyqa"))
fit.all <- lmer(Net_payoff ~ Round + as_factor(Treatment)*abs(Drawn)+
(gender) + age + risk_taker + (trust_scale ) +(honesty_scale)
+(1|session.code:participant.code) ,
data=d.reg %>% filter(gender!="Non binario"), control=lmerControl(optimizer= "bobyqa"))
#--------------------------------------------------
htmlreg(list(fit.A,fit.B,fit.C,fit.all),
custom.model.names = c("A","B","C","all"),
single.row = TRUE,
bold = 0.05,
booktabs = TRUE,
dcolumn = TRUE,
digits=3,
stars = c(0.001, 0.01, 0.05, 0.1))| A | B | C | all | |
|---|---|---|---|---|
| (Intercept) | 747.561 (103.270)*** | 554.838 (74.679)*** | 432.068 (50.382)*** | 661.643 (87.167)*** |
| Round | -0.017 (0.849) | -0.375 (0.887) | 1.384 (0.444)** | 0.481 (0.515) |
| as_factor(Treatment)Competition | -58.166 (22.831)* | -42.114 (18.838)* | -25.561 (16.365) | -59.807 (24.510)* |
| Drawn | 10.456 (0.518)*** | -8.765 (0.544)*** | ||
| genderMaschio | -2.442 (22.002) | -2.335 (16.808) | -12.974 (12.597) | -7.964 (20.593) |
| age | 1.375 (4.534) | 6.762 (3.230)* | 0.569 (1.845) | 0.016 (3.580) |
| risk_taker | -4.285 (5.509) | 8.078 (4.696)· | 0.005 (3.148) | 0.663 (5.270) |
| trust_scale | -8.975 (12.549) | 4.423 (10.901) | -4.570 (5.906) | -10.068 (11.359) |
| honesty_scale | 28.465 (18.762) | -10.934 (16.220) | -6.104 (11.790) | -6.314 (17.994) |
| as_factor(Treatment)Competition:Drawn | 1.432 (0.734)· | -3.200 (0.760)*** | ||
| abs(Drawn) | 2.589 (0.452)*** | 1.118 (0.525)* | ||
| as_factor(Treatment)Competition:abs(Drawn) | 2.090 (0.636)** | 1.790 (0.739)* | ||
| AIC | 27169.835 | 27299.463 | 25149.084 | 82745.975 |
| BIC | 27236.367 | 27365.995 | 25215.805 | 82825.754 |
| Log Likelihood | -13572.918 | -13637.732 | -12562.542 | -41360.988 |
| Num. obs. | 1890 | 1890 | 1920 | 5700 |
| Num. groups: session.code:participant.code | 63 | 63 | 64 | 190 |
| Var: session.code:participant.code (Intercept) | 3554.789 | 316.658 | 1327.957 | 15593.552 |
| Var: Residual | 101993.382 | 111379.052 | 28117.934 | 112436.068 |
| ***p < 0.001; **p < 0.01; *p < 0.05; ·p < 0.1 | ||||
- using sum at the group level (robustness check)
fit.all <- lmer(Net_payoff ~ Round + as_factor(Treatment)*abs(Drawn)
+(1|session.code) ,
data=d.reg %>% mutate(Group_ID=paste(session.code,Group,Round,sep="_")) %>% group_by(session.code,Group_ID,Drawn,Round,Treatment) %>% summarise_at("Net_payoff",sum), control=lmerControl(optimizer= "bobyqa"))
htmlreg(list(fit.all),
custom.model.names = c("all"),
single.row = TRUE,
bold = 0.05,
booktabs = TRUE,
dcolumn = TRUE,
digits=3,
stars = c(0.001, 0.01, 0.05, 0.1))| all | |
|---|---|
| (Intercept) | 1949.883 (36.388)*** |
| Round | 1.013 (0.719) |
| as_factor(Treatment)Competition | -194.002 (52.085)*** |
| abs(Drawn) | 3.395 (0.727)*** |
| as_factor(Treatment)Competition:abs(Drawn) | 5.316 (1.020)*** |
| AIC | 26980.908 |
| BIC | 27019.829 |
| Log Likelihood | -13483.454 |
| Num. obs. | 1920 |
| Num. groups: session.code | 7 |
| Var: session.code (Intercept) | 3909.646 |
| Var: Residual | 73958.664 |
| ***p < 0.001; **p < 0.01; *p < 0.05; ·p < 0.1 | |
- Are payoffs of DM higher in the last 15 rounds?
#--------------------------------------------------
fit.C.rob <- lmer(Net_payoff ~ ifelse(Round>15,1,0) + as_factor(Treatment) *abs(Drawn)+
(gender) + age + risk_taker + (trust_scale ) +(honesty_scale)
+(1|session.code:participant.code) ,
data=d.reg %>% filter(Type=="C"), control=lmerControl(optimizer= "bobyqa"))
#--------------------------------------------------
htmlreg(list(fit.C.rob),
custom.model.names = c("C rob"),
single.row = TRUE,
bold = 0.05,
booktabs = TRUE,
dcolumn = TRUE,
digits=3,
stars = c(0.001, 0.01, 0.05, 0.1))| C rob | |
|---|---|
| (Intercept) | 443.813 (50.055)*** |
| ifelse(Round > 15, 1, 0) | 19.922 (7.674)** |
| as_factor(Treatment)Competition | -25.387 (16.371) |
| abs(Drawn) | 2.562 (0.452)*** |
| genderMaschio | -12.955 (12.598) |
| age | 0.577 (1.845) |
| risk_taker | 0.010 (3.149) |
| trust_scale | -4.570 (5.907) |
| honesty_scale | -6.139 (11.791) |
| as_factor(Treatment)Competition:abs(Drawn) | 2.079 (0.636)** |
| AIC | 25146.368 |
| BIC | 25213.089 |
| Log Likelihood | -12561.184 |
| Num. obs. | 1920 |
| Num. groups: session.code:participant.code | 64 |
| Var: session.code:participant.code (Intercept) | 1326.815 |
| Var: Residual | 28163.109 |
| ***p < 0.001; **p < 0.01; *p < 0.05; ·p < 0.1 | |
6 Additional Results
6.1 Benchmarks
# Typ: A, B (S1,S2) or C (DM)
# Treatm: Competition or Monopoly
#ref: the benchamrk
deviation <- function(Typ, Treatm,ref) {
x <- d |>
filter((Type %in% Typ) & Treatment == Treatm) |>
select(participant.code, Net_payoff) %>%
group_by(participant.code) |>
summarise_at("Net_payoff", ~ mean(.)) %>%
pull(Net_payoff)
dev=x-ref
dev_perc <- dev / ref
return(
paste(round(mean(dev_perc * 100), 3), " (", round(wilcox.test(dev_perc)$p.value, 3),")",sep="")
)
}| Benchmark | DM | S1 | S2 | TOT |
|---|---|---|---|---|
| Complete Info | 600 | 800 | 800 | 2200 |
| No Communication | 400 | 800 | 800 | 2000 |
| Cheap Talk | 400 | 800 | 800 | 2000 |
Deviatons from benchmark in % terms
6.1.1 Competition
| Benchmark | DM | S1 | S2 | TOT |
|---|---|---|---|---|
| Complete Info | -17.361 (0) | -7.629 (0.002) | -15.074 (0) | 2200 |
| No Communication | 23.958 (0) | -7.629 (0.002) | -15.074 (0) | 2000 |
| Cheap Talk | 23.958 (0) | -7.629 (0.002) | -15.074 (0) | 2000 |
6.1.2 Monopoly
| Benchmark | DM | S1 | S2 | TOT |
|---|---|---|---|---|
| Complete Info | -18.542 (0) | -2.712 (0.214) | -8.021 (0) | 2200 |
| No Communication | 22.188 (0) | -2.712 (0.214) | -8.021 (0) | 2000 |
| Cheap Talk | 22.188 (0) | -2.712 (0.214) | -8.021 (0) | 2000 |
6.1.3 Equilibrium
| SETTING - EQM | DM | S1 | S2 | TOT |
|---|---|---|---|---|
| MONO-MIE | 600 | 483.09 | 800 | 1883.09 |
| MONO-LIE | 410.96 | 800 | 421.92 | 1694.05 |
| COMP-MIE | 600 | 483.09 Oor 800 | 800 or 483.09 | 1883.09 |
| COMP-AE | 449.08 | 561.84 | 561.84 | 1572.76 |
| SETTING - EQM | DM | S1 | S2 | TOT |
|---|---|---|---|---|
| MONO-MIE | -18.542 (0) | 61.11 (0) | -8.021 (0) | 1883.09 |
| MONO-LIE | 18.929 (0) | -2.712 (0.214) | 74.401 (0) | 1694.05 |
| COMP-MIE | -17.361 (0) | 52.967 (0) or -7.629 (0.002) | -15.074 (0) or 40.638 (0) | 1883.09 |
| COMP-AE | 10.411 (0) | 31.526 (0) | 20.926 (0) | 1572.76 |
6.2 Decision Times
# join choices and times
IDa <- d %>% filter(Type=="A") %>% distinct(participant.code) %>% pull()
IDb <- d %>% filter(Type=="B") %>% distinct(participant.code) %>% pull()
IDc <- d %>% filter(Type=="C") %>% distinct(participant.code) %>% pull()
# codification error for session.code = 7lq6t6as, participant.code = yerm0n2w -> remove time on page =0
d.j <-
full_join(
d,
bind_rows(
d.t %>% filter(participant.code %in% IDa) %>% filter(page_name=="Slider_A") %>% filter(time_on_page!=0)%>% select(session_code, participant.code,time_on_page, round_number) %>% rename(Round=round_number,session.code=session_code),
d.t %>% filter(participant.code %in% IDb) %>% filter(page_name=="Slider_B") %>% filter(time_on_page!=0)%>% select(session_code, participant.code,time_on_page, round_number) %>% rename(Round=round_number,session.code=session_code),
d.t %>% filter(participant.code %in% IDc) %>% filter(page_name=="Slider_C") %>% filter(time_on_page!=0)%>% select(session_code, participant.code,time_on_page, round_number) %>% rename(Round=round_number,session.code=session_code)
),
by=c("session.code","participant.code","Round")
) 6.2.1 Sender
- Times in Competition and Monopoly
d.j %>% filter(((Type == "A" | Type =="B") & Treatment=="Competition") | (Type == "A" & Treatment=="Monopoly")) %>% group_by(Treatment, participant.code) %>%
summarise_at("time_on_page",mean) %>%
summarise_at("time_on_page",list(N=~n(),Mean=~mean(.,na.rm=TRUE), SD=~sd(.,na.rm=TRUE), Median=~median(.,na.rm=TRUE))) %>%
kable() %>% kable_minimal()| Treatment | N | Mean | SD | Median |
|---|---|---|---|---|
| Competition | 64 | 20.34948 | 9.681219 | 19.05000 |
| Monopoly | 32 | 20.53125 | 6.456521 | 19.61667 |
- Test at the individual level
d.j %>% filter(((Type == "A" | Type =="B") & Treatment=="Competition") | (Type == "A" & Treatment=="Monopoly")) %>% group_by(Treatment, participant.code) %>%
summarise_at("time_on_page",mean) %>%
with(wilcox.test(time_on_page~Treatment)) %>% tidy() %>%
kable() %>% kable_minimal()| statistic | p.value | method | alternative |
|---|---|---|---|
| 950.5 | 0.5704491 | Wilcoxon rank sum test with continuity correction | two.sided |
- Time to lie and tell the truth
d.j %>% filter(((Type == "A" | Type =="B") & Treatment=="Competition") | (Type == "A" & Treatment=="Monopoly")) %>%
mutate(truth=ifelse((Type == "A" & Report_A == Drawn) | (Type == "B" & Report_B == Drawn), 1, 0)) %>%
group_by(truth, participant.code) %>%
summarise_at("time_on_page",mean) %>%
summarise_at("time_on_page",list(N=~n(),Mean=~mean(.,na.rm=TRUE), SD=~sd(.,na.rm=TRUE), Median=~median(.,na.rm=TRUE))) %>%
kable() %>% kable_minimal()| truth | N | Mean | SD | Median |
|---|---|---|---|---|
| 0 | 89 | 26.20470 | 15.062432 | 22.58333 |
| 1 | 93 | 17.91894 | 6.732458 | 16.26087 |
- Test at the individual level (average time when cheating and when not)
test <-
d.j %>% filter(((Type == "A" | Type =="B") & Treatment=="Competition") | (Type == "A" & Treatment=="Monopoly")) %>%
mutate(truth=ifelse((Type == "A" & Report_A == Drawn) | (Type == "B" & Report_B == Drawn), 1, 0)) %>%
group_by(truth, participant.code) %>%
summarise_at("time_on_page",mean)
wilcox.test(
full_join(test %>% filter(truth==0), test %>% filter(truth==1), by=c("participant.code")) %>% pull(time_on_page.x),
full_join(test %>% filter(truth==0), test %>% filter(truth==1), by=c("participant.code")) %>% pull(time_on_page.y),
paired=TRUE
) %>% tidy() %>%
kable() %>% kable_minimal()| statistic | p.value | method | alternative |
|---|---|---|---|
| 3254.5 | 0 | Wilcoxon signed rank test with continuity correction | two.sided |
6.2.2 Decision Maker
- Times in Competition and Monopoly
d.j %>% filter(Type=="C") %>% group_by(Treatment, participant.code) %>%
summarise_at("time_on_page",mean) %>%
summarise_at("time_on_page",list(N=~n(),Mean=~mean(.,na.rm=TRUE), SD=~sd(.,na.rm=TRUE), Median=~median(.,na.rm=TRUE))) %>%
kable() %>% kable_minimal()| Treatment | N | Mean | SD | Median |
|---|---|---|---|---|
| Competition | 32 | 13.45208 | 6.737085 | 12.03333 |
| Monopoly | 32 | 11.58229 | 4.656140 | 10.63333 |
- Test at the individual level
| statistic | p.value | method | alternative |
|---|---|---|---|
| 583 | 0.3438077 | Wilcoxon rank sum test with continuity correction | two.sided |
- Time to choose for conflicting values in Competition
d.j %>% filter(Type=="C" & Treatment == "Competition") %>% mutate(conflicting=ifelse(Report_B!=0,ifelse((Report_A/Report_B)>0,0,1),ifelse(Report_A==0,0,1))) %>%
group_by(conflicting, participant.code) %>%
summarise_at("time_on_page",mean) %>%
summarise_at("time_on_page",list(N=~n(),Mean=~mean(.,na.rm=TRUE), SD=~sd(.,na.rm=TRUE), Median=~median(.,na.rm=TRUE))) %>%
kable() %>% kable_minimal()| conflicting | N | Mean | SD | Median |
|---|---|---|---|---|
| 0 | 32 | 10.80826 | 5.888778 | 8.846154 |
| 1 | 32 | 16.50154 | 9.722316 | 14.444444 |
- Test at the individual level (average time when conflicting and when not)
| statistic | p.value | method | alternative |
|---|---|---|---|
| 57 | 3.18e-05 | Wilcoxon signed rank exact test | two.sided |
6.3 Spectator Beliefs
Take median value of the intervals
# - Bel_A1: the probability that Player A is going to report the value truthfully
#1: 0%-20%; 2:21%-40%; 3:41%-60%; 4:61%-80%; 5:81%-100%<
# - Bel_A2: the probability that Player C is going to choose Black
#1: 0%-20%; 2:21%-40%; 3:41%-60%; 4:61%-80%; 5:81%-100%<
interval = list(.10, .30, .50, .70, .90)
d.bel <-
d %>% filter(Treatment=="Monopoly" & Type=="B") %>%
select(Treatment,session.code,participant.code,Type,Round,Drawn,Report_A,Choice_C, Bel_A1, Bel_A2, Drawn, Report_A) %>%
mutate(Bel_A1_perc=unlist(interval[Bel_A1])*100, Bel_A2_perc=unlist(interval[Bel_A2])*100)6.3.1 Beliefs of truthful report (conditional upon signal)
| positive | N | Mean | SD | Median |
|---|---|---|---|---|
| 0 | 32 | 49.73235 | 11.35923 | 50.62500 |
| 1 | 32 | 67.27166 | 11.98553 | 66.30682 |
- Test at the individual level (when drawning a positive and a negative value)
| statistic | p.value | method | alternative |
|---|---|---|---|
| 20 | 2e-07 | Wilcoxon signed rank exact test | two.sided |
- Are beliefs correct?
| truth_telling | N | Mean | SD | Median |
|---|---|---|---|---|
| 0 | 418 | 55.16746 | 25.39087 | 50 |
| 1 | 542 | 60.88561 | 26.48108 | 70 |
| statistic | p.value | method | alternative |
|---|---|---|---|
| 195 | 0.3035649 | Wilcoxon signed rank test with continuity correction | two.sided |
6.3.2 Beliefs that DM chooses BLACK conditional upon reported value
| positive | N | Mean | SD | Median |
|---|---|---|---|---|
| 0 | 32 | 31.54433 | 16.38314 | 27.57143 |
| 1 | 32 | 68.96090 | 11.41990 | 70.00000 |
- Test at the individual level (when the other reports a positive and a negative value)
| statistic | p.value | method | alternative |
|---|---|---|---|
| 2.5 | 1.1e-06 | Wilcoxon signed rank test with continuity correction | two.sided |
- Are beliefs correct?
| follows | N | Mean | SD | Median |
|---|---|---|---|---|
| 0 | 447 | 41.09620 | 28.82462 | 30 |
| 1 | 513 | 69.61014 | 23.24807 | 70 |
| statistic | p.value | method | alternative |
|---|---|---|---|
| 2 | 0 | Wilcoxon signed rank exact test | two.sided |