champagne anarchist | armchair activist


Assignment 1-3

A little background: I’m using the Outlook on Life Surveys dataset and I’m interested in the relation between union membership and political participation (background here). The third assignment is similar to the second one, only we’re required to do some data management before outputting the data. Therefore, I’ll submit an adapted version of the programme and blogpost of the previous assignment.

The output’s supposed to be ‘interpretable (i.e. organized and labeled)’. For those who are logged in to the course website, I refer to this forum post disucssing how I interpreted this requirement.

In terms of data management, I’ll perform the following steps: first recode ‘refused’ to NaN (not required for the first variable PPWORK, because it has no missing values) and recode the answers to labels (e.g. 1 = ‘Yes’). Next, I’ll create a secondary variable which indicates whether respondents have engaged in any of the four types of political participation discussed below.

The programme itself is posted here. Below I’ll discuss some of the output. For the sake of convenience, I’ll only show percentages (the raw counts can be obtained by running the programme). First, the current employment status of respondents.

PPWORK: Current Employment Status
Not working - retired                           21.011334
Not working - on temporary layoff from a job     1.264167
Not working - looking for work                  10.854403
Not working - disabled                           8.456844
Not working - other                              6.451613
Working - self-employed                          6.190061
Working - as a paid employee                    45.771578
dtype: float64

One of the variables I’m interested in, is union membership. My understanding of the American situation is that union membership is often dependent on whether your workplace is organised (by contrast, in the Netherlands it’s not uncommon for unemployed or retired people to be union members). For that reason, it makes sense to look specifically at respondents who are working as paid employees. (The fact that union membership is measured at the household level complicates matters but that doesn’t change my preference to focus on paid employees.)

1,050 respondents (46%) are paid employees. This would seem to be a sufficiently large group for the purposes of the analyses I plan to do. In the programme, I created at subset of respondents who indicated they are working as paid employees. All output below is based on this subset.

Next, let’s take a look at the numbers for the variable on union membership (as indicated, at the household level).

W1_P8: Does anyone in your household currently belong to a union?
NaN     1.142857
No     78.380952
Yes    20.476190
dtype: float64

Within the subset of respondents with paid employment, little over 20% indicate that at least one person in their household is a union member. This compares to a union density of 11.1% among wage and salary workers in the US according to the Bureau of Labour Statistics.

Some of that difference can be explained by the fact that the 20% figure will include some respondents who aren’t union members themselves but who have someone in their household who is. On the other hand, the BLS is a bit more persistent in assessing union membership, and would likely classify some people as union members who wouldn’t be classified as such in the OOL surveys.[1] All in all, I’m inclined to say the 20% figure in the OOL surveys is higher than expected and that there is a possiblity that the survey sample is in some way biased towards union members.

And finally the political participation measures.

W1_L4_A: [Contacted a public official or agency ] Please indicate if you have done any of the following activities in the last 2 years.
NaN     2.190476
No     74.095238
Yes    23.714286
dtype: float64
W1_L4_B: [Attended a protest meeting or demonstration ] Please indicate if you have done any of the following activites in the last 2 years.
NaN     2.190476
No     90.571429
Yes     7.238095
dtype: float64
W1_L4_C: [Taken part in a neighborhood march ] Please indicate if you have done any of the following activites in the last 2 years.
NaN     2.095238
No     93.047619
Yes     4.857143
dtype: float64
W1_L4_D: [Signed a petition in support of something or against something ] Please indicate if you have done any of the following activites in the last 2 years.
NaN     2.380952
No     58.190476
Yes    39.428571
dtype: float64

Respondents are more likely to have signed a petition or contacted an offical than to have hit the streets. This is as expected.

I’ve created a secondary variable indicating whether respondents have participated in any of the discussed forms of political participation. Respondents who have answered ‘Yes’ to any of the four political participation questions will be assigned a value ‘Yes’; those who have answered ‘No’ to all four questions will be assigned a value ‘No’ and those who have not answered ‘Yes’ to any of the questions but who have refused to answer at least one of the questions will be treated as missing.

ANY: Respondent has engaged in any of the four forms of political participation in the last 2 years
NaN     2.190476
No     50.952381
Yes    46.857143
dtype: float64

The frequency table shows that almost half the respondents have engaged in any of the discussed forms of political participation in the last 2 years.

Finally a word on missing values. For all variables considered here, the percentage ‘refused’ is below 2.5%. This would seem sufficiently low not to expect any problems arising from this.

PS One of the students who reviewed my first assigment suggested I include ‘canvassing’ as a measure of political participation, which seems to make sense. Unfortunately the dataset doesn’t seem to include this aspect, but there are variables on other types of political participation that I may add in the future.

  1. «Employed wage and salary workers are classified as union members if they answer “yes” to the following question: On this job, are you a member of a labor union or of an employee association similar to a union? If the response is “no” to that question, then the interviewer asks a second question: On this job, are you covered by a union or employee association contract? If the response is “yes,” then these persons, along with those who responded “yes” to being union members, are classified as represented by a union. If the response is “no” to both the first and second questions, then they are classified as nonunion.»  ↩

Coursera Data Analysis and Interpretation

I was initially introduced to R by Nathan Yau’s Visualize This, but subsequently I learned a lot about R through some of the courses in Brian Caffo, Roger Peng and Jeff Leek’s Data Science Specialization at Coursera. In fact, the course was a reason for me to postpone switching from R to Python.

By now, I’ve decided to make the switch anyhow, and I think I’ve found another Coursera specialisation that will help me learn the tricks: Lisa Dierker and Jen Rose’s Data Analysis and Interpretation. It’s kind of basic, at least at the beginning, but that’s good. Some of the assignments require you to blog about a project of your choosing, so I’ll be posting about my homework here.

Base versus ggplot2

Yesterday, stats guru Jeff Leek confessed the ultimate unpopular opinion in data science: «I don’t use ggplot2 and I get nervous when other people do» (if you haven’t a clue what this is about, you may want to skip this post altogether). His confession met with ridicule, more riducule, and an occasional «oh my god I thought I was the only one!».

I sort of assumed everybody uses ggplot now. I was wrong: I like base for graphics, is that weird? * Buena referencia para graficas base! (si como yo, odian ggplot). * base graphics FTW re:slopegraph (it’s a royal pain to do this in ggplot). * I’m not a fan of ggplot. * Retro! * I kinda hate ggplot. * Vigorous group discussion on the merits of base plot vs #ggplot in #rstats.

For me, it’s six of one and half a dozen of the other: I’m planning to switch to Python.

Komen stadsdeelpolitici op landelijke TV? Gegevens uit de NPO Backstage API

Laatst heb ik gekeken hoe vaak Amsterdamse politici worden genoemd op de websites van het Parool en AT5. Voorlopige conclusie: de belangstelling voor de stadsdeelpolitiek lijkt te zijn ingezakt sinds de macht van de stadsdelen is ingeperkt per maart 2014.

Toen ik vervolgens een artikel tegenkwam waarin wordt uitgelegd hoe makkelijk je aan gegevens kan komen over NPO-programma’s, heb ik ook nog een blik geworpen op de belangstelling van de publieke omroep voor de Amsterdamse politiek.

Met een slag om de arm (zie hieronder, Methode) zijn de resultaten: in de raadsperiode tot maart 2014 werden gemeentepolitici 28 keer genoemd en stadsdeelpolitici 18 keer. Sinds de hervorming van het bestuurlijke stelsel in maart 2014 werden gemeentepolitici 11 keer genoemd en stadsdeelpolitici nog maar 3 keer (de grafiek toont het gemiddelde aantal vermeldingen per 100 dagen). Dit lijkt dus het beeld te bevestigen dat stadsdeelpolitiek in de ogen van de redacties minder relevant is geworden.

In de periode 2010–2014 zijn de volgende stadsdeelpolitici genoemd (of hun naamgenoten):

  • Fatima Elatik (4 keer): Over Marokkaanse jongeren, lipstick moslims en haar werk als stadsdeelvoorzitter.
  • Henk de Boer (2 keer): Iemand anders met dezelfde naam?
  • Ronald Mauer: Over de dood van een grensrechter in Nieuw-Sloten.
  • Jeroen Mirck: Kwam als internetjournalist aan het woord in een programma over Rutger Castricum.
  • Frans Icke: Over zweefvliegen. Iemand anders met dezelfde naam?
  • Jeroen van Spijk: Over parkeertarieven in Oost (AT5-fragment bij De Wereld Draait Door).
  • Boudewijn Oranje: Over de sloopplannen van de UvA voor het BG-terrein.
  • Jan Engel: Iemand anders met dezelfde naam?
  • Stefan de Bruijn: Over de vluchtkerk (aangekondigd als gemeenteraadslid, maar dat terzijde).
  • Martien Kuitenbrouwer: Naar aanleiding van de juwelier in de Jan Evertsenstraat die werd doodgeschoten bij een overval.
  • Coby van Berkum: Over het dreigende verlies van de PvdA bij de verkiezingen van maart 2014.
  • Ahmed Baâdoud: Over liquidaties.
  • Bart van der Linden: Iemand anders met dezelfde naam?
  • Joël Andoetoe: Over de VVD en de affaire-Van Reij.

En in de huidige periode:

  • Jeroen van Berkel: Iemand anders met dezelfde naam?
  • Frans Icke: Zie hierboven.
  • Alexander Hammelburg: Kwam als politicoloog aan het woord over Saoedisch ingrijpen in Jemen.

In verschillende gevallen lijkt er sprake te zijn van naamgenoten die niets te maken hebben met de stadsdeelpolitiek. Wanneer er daadwerkelijk stadsdeelpolitici op de landelijke TV komen, dan gaat het lang niet altijd over stadsdeelpolitiek. Maar in zijn algemeenheid kan je wel zeggen dat stadsdeelpolitici in de vorige periode vaker werden gezien als relevante bron over wat er speelt in Amsterdam.


Zoeken via de NPO Backstage API is op zich vrij eenvoudig en je hoeft niet eens te registreren (!). Bovendien staan op Github verschillende voorbeelden van Pythoncode die laten zien hoe de API werkt.

Ik stuitte wel op het probleem dat er aanvankelijk veel dubbelingen in m’n zoekresultaten zaten. Dit komt doordat de API verschillende soorten informatie bevat zoals een algemene beschrijving van een programma; een beschrijving van metadata en voor sommige programma’s de tekst van de complete ondertiteling voor slechthorenden.

Ik besloot om te zoeken in de ondertitelingen. Op die manier voorkom je veel dubbelingen en gebruik je een consistente dataset. Tegelijk is het wel zo dat de ondertiteling niet van alle programma’s beschikbaar is. Daardoor mis je bijvoorbeeld het radio-optreden van Rutger Groot Wassink bij de EO, waarin hij zijn boycot van de gemeentelijke nieuwjaarsreceptie toelicht.

Met een zoekopdracht binnen de set ondertitelingen hou je nog steeds dubbelingen over, omdat programma’s soms herhaald worden. Het item met Jeroen Mirck over Rutger Castricum bijvoorbeeld is drie keer uitgezonden. Die uitzendingen hebben allemaal een eigen prid (programma-ID), dus daarmee los je het probleem niet op.

De herhalingen heb ik geprobeerd eruit te filteren op basis van de eerste vijftig karakters van de programmabeschrijving (en vervolgens heb ik van alle bijbehorende uitzenddatums de oudste genomen). Deze methode is niet waterdicht: aan de ene kant kunnen er inconsistenties zitten in de programmabeschrijving en aan de andere kant wordt soms dezelfde omschrijving gebruikt voor alle afleveringen van een serie programma’s. Op die manier kan het gebeuren dat meerdere optredens bij Pauw en Witteman ten onrechte worden geteld als één optreden. Pragmatisch gezien denk ik dat de verstorende werking hiervan minder ernstig is dan wanneer je herhalingen meetelt als afzonderlijke optredens. Maar het blijft een beetje een los eindje.

Een voorbeeld van een url voor een zoekopdracht is Je bladert door de resultaten door de waarde van from telkens met 100 te verhogen totdat deze waarde hoger is dan het totale aantal resultaten. Vervolgens kan je voor elk resultaat details zoals de datum opzoeken via een url waarin de prid is verwerkt, bijvoorbeeld

Voor de manier waarop ik namen van politici heb verzameld en de uiteindelijke resultaten heb geanalyseerd, zie m’n eerdere artikel over lokale media.

De NPO Backstage API is ontwikkeld door de Open State Foundation die zich inzet voor toegankelijke overheidsinformatie. De stichting zat ook achter Politwoops, de site waar verwijderde tweets van politici werden gearchiveerd - totdat Twitter hier een stokje voor stak.

Apparently, it’s still possible to fool Google

Researchers have found that men are almost six times more likely than women to be shown ads on news websites for a career coaching service for $200k+ executive positions. The findings suggest some of the algorithms involved in tracking internet users have discriminatory outcomes. They might lead to «deeper investigations by either the companies themselves or by regulatory bodies», the authors add (via WP).

Not just the findings are interesting, but so is the research method. The researchers created AdFisher, basically a smart web scraper built with Python. AdFisher can create large numbers of «agents», have them visit certain websites or alter their profile via the Google Ad Settings, and then see what ads it gets shown on websites like the Times of India or the Guardian. Further, it will organise these activities in such a way that experimental and control conditions can be compared, and it will even analyse the results, using machine learning to figure out what may have triggered differences in what ads are shown.

Somehow this reminded me of the patent Apple (!) obtained for a cloning service to fool the companies that are tracking you. The service would mimick some of your normal online behaviour, but also do other stuff, such as faking an interest in basket weaving. This way it would contaminate the profile these companies keep of you, perhaps to the point of making it useless.

So would you be able to get away with that? If you open a bunch of browser windows with Google searches, Google will ask you to fill out a captcha to make sure you’re human («Our systems have detected unusual traffic from your computer network. This page checks to see if it’s really you sending the requests, and not a robot»). This is a very simple example, but given the fast-developing ability to analyse patterns in online behaviour, you’d expect that companies like Google and Facebook would have become eerily accurate at identifying (real) internet users and telling them from bots.

Against that background, it’s somehow reassuring that it’s apparently still possible to fool Google by creating a fake profile.

P.s. I’ve never been shown ads for a career coaching service for $200k+ executive positions, but if they do turn up I’ll just tell Google I’m a woman.