voters
Topics to me as soon as possible
Date | Presenters | Method |
---|---|---|
15 May: | Idil M., Zeynep P., Liesl W., Selin K., Chiara W. | logistic regression |
22 May: | Gabriel W., Lina M., Florian S., Julian B. | discourse analysis |
29 May: | NO CLASS MEETING |
Date | Presenters | Method |
---|---|---|
5 June: | Rasmus B., Andre D., Josefine E., Ioanna L., Santiago C. | regression |
12 June: | Omar B., Lela E., Niclas W. | TBD |
19 June: | NO CLASS MEETING | |
26 June: | Colombe I., Konstantin S., Jakob W., Veronika L. | TBD |
26 June: | Maksim K., Felix S., Jon L.D., Damir S., Korbinian M. | case study |
Date | Presenters | Method |
---|---|---|
3 July: | Alexander V., Luis G., Oscar O., Mia C. | TBD |
10 July: | Lina S., Stephen W., Philomena B., Aarón Z. | TBD |
17 July: | Corinna Z., Eva M., and Rostislav N. | TBD |
24 July: | Sebastian K., Thomas R., Emilia Z., Florian P. | TBD |
24 July: | Lorenz F., Daniel B., Fiona W., Medina H. | quant. text analysis |
rising local rental prices increase probability of support (AfD) among renters with lower household income (Abou-Chadi, Cohen, and Kurer 2024)
(video from just before 2024 EU elections)
Observations:
Theses:
Take the survey at https://forms.gle/im5PVyqQeGNw8FWg8
import { liveGoogleSheet } from "@jimjamslam/live-google-sheet";
import { aq, op } from "@uwdata/arquero";
// UPDATE THE LINK FOR A NEW POLL
surveyResults = liveGoogleSheet(
"https://docs.google.com/spreadsheets/d/e/" +
"2PACX-1vQI6wQF677rVAuYzA5e5tADcPH6YonPxUDzJLyiJudY31kToPsM3-u4lglGpgRXOUDTza3wTpPh9qW8/" +
"pub?gid=1789095757&single=true&output=csv",
10000, 1, 6); // adjust the last number to select all relevant columns
respondentCount = surveyResults.length;
Rational choice?
rationalCounts = aq.from(surveyResults)
.select("rational")
.groupby("rational")
.count()
.derive({ measure: d => "" })
// Calculate the maximum count from your dataset
rational_maxCountRE = Math.max(...rationalCounts.objects().map(d => d.count));
plot_rational = Plot.plot({
marks: [
Plot.barY(rationalCounts, {
x: "rational",
y: "count",
fill: "rational",
stroke: "black",
strokeWidth: 1
}),
Plot.ruleY([respondentCount], { stroke: "#ffffff99" })
],
color: {
domain: [
"Yes",
"No"
],
range: [
"forestgreen",
"darkred"
]
},
marginBottom: 80,
x: { label: "", tickSize: 2, tickRotate: -25,
domain: ["Yes", "No"]
},
y: {
label: "",
tickSize: 10,
tickFormat: d => d,
tickValues: Array.from(
new Set(rationalCounts.objects().map(d => d.count))
).sort((a, b) => a - b),
domain: [0, rational_maxCountRE]
},
facet: { data: rationalCounts, x: "measure", label: "" },
marginLeft: 140,
style: {
width: 1350,
height: 500,
fontSize: 30,
}
});
Misinformed, manipulated?
misinformedCounts = aq.from(surveyResults)
.select("misinformed")
.groupby("misinformed")
.count()
.derive({ measure: d => "" })
// Calculate the maximum count from your dataset
misinformed_maxCountRE = Math.max(...misinformedCounts.objects().map(d => d.count));
plot_misinformed = Plot.plot({
marks: [
Plot.barY(misinformedCounts, {
x: "misinformed",
y: "count",
fill: "misinformed",
stroke: "black",
strokeWidth: 1
}),
Plot.ruleY([respondentCount], { stroke: "#ffffff99" })
],
color: {
domain: [
"Yes",
"No"
],
range: [
"forestgreen",
"darkred"
]
},
marginBottom: 80,
x: { label: "", tickSize: 2, tickRotate: -25,
domain: ["Yes", "No"]
},
y: {
label: "",
tickSize: 10,
tickFormat: d => d,
tickValues: Array.from(
new Set(misinformedCounts.objects().map(d => d.count))
).sort((a, b) => a - b),
domain: [0, misinformed_maxCountRE]
},
facet: { data: misinformedCounts, x: "measure", label: "" },
marginLeft: 140,
style: {
width: 1350,
height: 500,
fontSize: 30,
}
});
Rational choice?
plot_rational1 = Plot.plot({
marks: [
Plot.barY(rationalCounts, {
x: "rational",
y: "count",
fill: "rational",
stroke: "black",
strokeWidth: 1
}),
Plot.ruleY([respondentCount], { stroke: "#ffffff99" })
],
color: {
domain: [
"Yes",
"No"
],
range: [
"forestgreen",
"darkred"
]
},
marginBottom: 80,
x: { label: "", tickSize: 2, tickRotate: -25,
domain: ["Yes", "No"]
},
y: {
label: "",
tickSize: 10,
tickFormat: d => d,
tickValues: Array.from(
new Set(rationalCounts.objects().map(d => d.count))
).sort((a, b) => a - b),
domain: [0, rational_maxCountRE]
},
facet: { data: rationalCounts, x: "measure", label: "" },
marginLeft: 140,
style: {
width: 1350,
height: 500,
fontSize: 30,
}
});
Misinformed, manipulated?
plot_misinformed1 = Plot.plot({
marks: [
Plot.barY(misinformedCounts, {
x: "misinformed",
y: "count",
fill: "misinformed",
stroke: "black",
strokeWidth: 1
}),
Plot.ruleY([respondentCount], { stroke: "#ffffff99" })
],
color: {
domain: [
"Yes",
"No"
],
range: [
"forestgreen",
"darkred"
]
},
marginBottom: 80,
x: { label: "", tickSize: 2, tickRotate: -25,
domain: ["Yes", "No"]
},
y: {
label: "",
tickSize: 10,
tickFormat: d => d,
tickValues: Array.from(
new Set(misinformedCounts.objects().map(d => d.count))
).sort((a, b) => a - b),
domain: [0, misinformed_maxCountRE]
},
facet: { data: misinformedCounts, x: "measure", label: "" },
marginLeft: 140,
style: {
width: 1350,
height: 500,
fontSize: 30,
}
});
supportCounts = aq.from(surveyResults)
.select("support")
.groupby("support")
.count()
.derive({ measure: d => "" })
// Calculate the maximum count from your dataset
support_maxCountRE = Math.max(...supportCounts.objects().map(d => d.count));
plot_support = Plot.plot({
marks: [
Plot.barY(supportCounts, {
x: "support",
y: "count",
fill: "support",
stroke: "black",
strokeWidth: 1
}),
Plot.ruleY([respondentCount], { stroke: "#ffffff99" })
],
color: {
domain: [
"Protest",
"Genuine support"
],
range: [
"darkorchid",
"gold"
]
},
marginBottom: 80,
x: { label: "", tickSize: 2, tickRotate: -25,
domain: ["Protest", "Genuine support"]
},
y: {
label: "",
tickSize: 10,
tickFormat: d => d,
tickValues: Array.from(
new Set(supportCounts.objects().map(d => d.count))
).sort((a, b) => a - b),
domain: [0, support_maxCountRE]
},
facet: { data: supportCounts, x: "measure", label: "" },
marginLeft: 140,
style: {
width: 1350,
height: 500,
fontSize: 30,
}
});
motivatedCounts = aq.from(surveyResults)
.select("motivated")
.groupby("motivated")
.count()
.derive({ measure: d => "" })
// Calculate the maximum count from your dataset
motivated_maxCountRE = Math.max(...motivatedCounts.objects().map(d => d.count));
plot_motivated = Plot.plot({
marks: [
Plot.barY(motivatedCounts, {
x: "motivated",
y: "count",
fill: "motivated",
stroke: "black",
strokeWidth: 1
}),
Plot.ruleY([respondentCount], { stroke: "#ffffff99" })
],
color: {
domain: [
"Economic insecurity",
"Cultural/identity concerns"
],
range: [
"dodgerblue",
"firebrick"
]
},
marginBottom: 80,
x: { label: "", tickSize: 2, tickRotate: -25,
domain: ["Economic insecurity", "Cultural/identity concerns"]
},
y: {
label: "",
tickSize: 10,
tickFormat: d => d,
tickValues: Array.from(
new Set(motivatedCounts.objects().map(d => d.count))
).sort((a, b) => a - b),
domain: [0, motivated_maxCountRE]
},
facet: { data: motivatedCounts, x: "measure", label: "" },
marginLeft: 140,
style: {
width: 1350,
height: 500,
fontSize: 30,
}
});
immigrationCounts = aq.from(surveyResults)
.select("immigration")
.groupby("immigration")
.count()
.derive({ measure: d => "" })
// Calculate the maximum count from your dataset
immigration_maxCountRE = Math.max(...immigrationCounts.objects().map(d => d.count));
plot_immigration = Plot.plot({
marks: [
Plot.barY(immigrationCounts, {
x: "immigration",
y: "count",
fill: "immigration",
stroke: "black",
strokeWidth: 1
}),
Plot.ruleY([respondentCount], { stroke: "#ffffff99" })
],
color: {
domain: [
"Actual immigration",
"Perception of immigration"
],
range: [
"darkslategray",
"paleturquoise"
]
},
marginBottom: 80,
x: { label: "", tickSize: 2, tickRotate: -25,
domain: ["Actual immigration", "Perception of immigration"]
},
y: {
label: "",
tickSize: 10,
tickFormat: d => d,
tickValues: Array.from(
new Set(immigrationCounts.objects().map(d => d.count))
).sort((a, b) => a - b),
domain: [0, immigration_maxCountRE]
},
facet: { data: immigrationCounts, x: "measure", label: "" },
marginLeft: 140,
style: {
width: 1350,
height: 500,
fontSize: 30,
}
});
plot_support1 = Plot.plot({
marks: [
Plot.barY(supportCounts, {
x: "support",
y: "count",
fill: "support",
stroke: "black",
strokeWidth: 1
}),
Plot.ruleY([respondentCount], { stroke: "#ffffff99" })
],
color: {
domain: [
"Protest",
"Genuine support"
],
range: [
"darkorchid",
"gold"
]
},
marginBottom: 80,
x: { label: "", tickSize: 2, tickRotate: -25,
domain: ["Protest", "Genuine support"]
},
y: {
label: "",
tickSize: 10,
tickFormat: d => d,
tickValues: Array.from(
new Set(supportCounts.objects().map(d => d.count))
).sort((a, b) => a - b),
domain: [0, support_maxCountRE]
},
facet: { data: supportCounts, x: "measure", label: "" },
marginLeft: 140,
style: {
width: 1350,
height: 500,
fontSize: 30,
}
});
plot_motivated1 = Plot.plot({
marks: [
Plot.barY(motivatedCounts, {
x: "motivated",
y: "count",
fill: "motivated",
stroke: "black",
strokeWidth: 1
}),
Plot.ruleY([respondentCount], { stroke: "#ffffff99" })
],
color: {
domain: [
"Economic insecurity",
"Cultural/identity concerns"
],
range: [
"dodgerblue",
"firebrick"
]
},
marginBottom: 80,
x: { label: "", tickSize: 2, tickRotate: -25,
domain: ["Economic insecurity", "Cultural/identity concerns"]
},
y: {
label: "",
tickSize: 10,
tickFormat: d => d,
tickValues: Array.from(
new Set(motivatedCounts.objects().map(d => d.count))
).sort((a, b) => a - b),
domain: [0, motivated_maxCountRE]
},
facet: { data: motivatedCounts, x: "measure", label: "" },
marginLeft: 140,
style: {
width: 1350,
height: 500,
fontSize: 30,
}
});
plot_immigration1 = Plot.plot({
marks: [
Plot.barY(immigrationCounts, {
x: "immigration",
y: "count",
fill: "immigration",
stroke: "black",
strokeWidth: 1
}),
Plot.ruleY([respondentCount], { stroke: "#ffffff99" })
],
color: {
domain: [
"Actual immigration",
"Perception of immigration"
],
range: [
"darkslategray",
"paleturquoise"
]
},
marginBottom: 80,
x: { label: "", tickSize: 2, tickRotate: -25,
domain: ["Actual immigration", "Perception of immigration"]
},
y: {
label: "",
tickSize: 10,
tickFormat: d => d,
tickValues: Array.from(
new Set(immigrationCounts.objects().map(d => d.count))
).sort((a, b) => a - b),
domain: [0, immigration_maxCountRE]
},
facet: { data: immigrationCounts, x: "measure", label: "" },
marginLeft: 140,
style: {
width: 1350,
height: 500,
fontSize: 30,
}
});
Values
Attitudes
Attitudes
Values
Values
Attitudes
Values
Attitudes
Values
Attitudes
values shape attitudes
(a full-length lecture: https://www.youtube.com/watch?v=8Qw8TtzjtL4. strongly recommended for those interested in party politics and/or doing their data report on a far-right party)
Stage 1: Values
Stage 2: Votes
Stage 3: Impacts
flowchart LR A[Structural<br/>change:<br/>generations,<br/>education,<br/>gender,<br/>diversity,<br/>urban]:::greenBox --> B[Silent<br/>revolution<br/>in socially-<br/>liberal<br/>values]:::greenBox C[Immigration<br/>& diversity] --> E{Tipping point:<br/>cultural backlash &<br/>authoritarian<br/>reflex}:::redBox B --> E D[Economic<br/>grievances] --> E F(electoral<br/>rules):::yellowBox --> H{Votes for<br/>A-P parties}:::yellowBox E --> H G(party<br/>competition):::yellowBox --> H H --> I[civic culture,<br/>policy agenda,<br/>& liberal democracy]:::blueBox %% Style definitions - classDef blueBox fill:#d0e6ff,stroke:#003366,stroke-width:2px; classDef blueBox fill:#d0e6ff; classDef greenBox fill:#d4edda; classDef greyBox fill:#e2e3e5; classDef redBox fill:#f8d7da; classDef yellowBox fill:#fff3cd;
under what conditions do far-right parties perform better at elections?
Opportunities:
factors/combinations enable far-right parties to surpass 20% ceiling
Anonymous feedback here: https://forms.gle/pisUmtmWdE13zMD58
Alternatively, send me an email: m.zeller@lmu.de