Fake News


In dit blog laat ik zien hoe ik de R library ‘ggplot’ heb gebruikt om fake news te maken! Dat wil zeggen: een grafiek met daarin een aangepast (hoger dan werkelijk) aantal bezoekers voor de DEEPMAP website. “Maar Sjoerd, dat kan toch ook gewoon met PhotoShop?” Natuurlijk, maar dit is veel leuker!

GGPLOT

Ggplot is een R library die gebruikt wordt voor visualisaties. Het fijne aan deze library is dat er zeer veel mogelijkheden zijn om grafieken tot op detailniveau aan te passen.

Als je liever de techniek overslaat en direct het resultaat wilt zien, klik dan hier.

Het doel

Voordat we beginnen met het maken van een visualisatie moeten we natuurlijk wel weten waar we ons op richten. De websites die ik beheer worden gehost door TransIP. Via het controlepaneel van deze aanbieder kan je eenvoudig zicht krijgen op het aantal bezoekers van de websites die je beheert. Hieronder zie je een afbeelding van de bezoekersaantallen van een hobby website die ik beheer (niet DEEPMAP.nl):

Lijkt eenvoudig, maar het zal redelijk wat aanpassingen vragen om tot een geloofwaardig resultaat te komen!

Lijkt eenvoudig, maar het zal redelijk wat aanpassingen vragen om tot een geloofwaardig resultaat te komen!

Let’s get started

Om data te kunnen visualiseren hebben we natuurlijk wel data nodig! In dit geval kopiëren we de data uit de screenshot hierboven. We hebben maar twee variabelen nodig: een datum en het aantal bezoekers. Dit doen we eenvoudig door het maken van een tabel met de tibble() functie.

# Maken van de tabel
real_news <- tibble(DATUM = seq(as.Date("2020-01-30"), 
                                as.Date("2020-02-06"), 
                                by = "1 day"),
                    BEZOEKERS = c(128, 57, 44, 146, 232, 436, 462, 0))

# Dit ziet er nu zo uit
real_news
## # A tibble: 8 x 2
##   DATUM      BEZOEKERS
##   <date>         <dbl>
## 1 2020-01-30       128
## 2 2020-01-31        57
## 3 2020-02-01        44
## 4 2020-02-02       146
## 5 2020-02-03       232
## 6 2020-02-04       436
## 7 2020-02-05       462
## 8 2020-02-06         0


We hebben iets om mee te werken! Alleen… de bezoekersaantallen uit dit voorbeeld vallen misschien toch een beetje tegen. Laten we zeggen dat we 20% meer bezoekers willen dan we hier zien staan!

# We maken fake_news
fake_news <- real_news %>%
  
  # 20% meer bezoekers, afgerond op hele aantallen
  mutate(BEZOEKERS = round(1.2 * BEZOEKERS, 0))

# Dit is beter
fake_news
## # A tibble: 8 x 2
##   DATUM      BEZOEKERS
##   <date>         <dbl>
## 1 2020-01-30       154
## 2 2020-01-31        68
## 3 2020-02-01        53
## 4 2020-02-02       175
## 5 2020-02-03       278
## 6 2020-02-04       523
## 7 2020-02-05       554
## 8 2020-02-06         0


Nice! Om het onszelf makkelijk te maken voegen we alvast wat tekst toe voor het label dat we gaan maken. In het origineel zie je een zwart veldje met daarin de tekst “04-02: 436 Bezoeker(s)”. Dit is de tekst die we nu vast aan onze data toevoegen.

# We maken een nieuwe kolom aan met allemaal lege waarden, behalve voor de gewenste datum
fake_news_label <- fake_news %>% 
  mutate(LABEL = if_else(DATUM == as.Date("2020-02-04"), "04-02: 523 Bezoeker(s)", ""))

# Fake news inclusief label
fake_news_label
## # A tibble: 8 x 3
##   DATUM      BEZOEKERS LABEL                   
##   <date>         <dbl> <chr>                   
## 1 2020-01-30       154 ""                      
## 2 2020-01-31        68 ""                      
## 3 2020-02-01        53 ""                      
## 4 2020-02-02       175 ""                      
## 5 2020-02-03       278 ""                      
## 6 2020-02-04       523 "04-02: 523 Bezoeker(s)"
## 7 2020-02-05       554 ""                      
## 8 2020-02-06         0 ""


In ggplot bouw je een grafiek op in verschillende lagen. Dat is wat we hieronder gaan doen. Het is heel eenvoudig om data op een snelle manier te visualiseren, iets dat veel gebruikt wordt om bekend te raken met de gegevens waar we mee werken. Het enige dat we moeten aangeven is welke data we gebruiken, welke variabelen we op de x-as en y-as willen weergeven en wat voor soort grafiek we willen maken.

Voor veel van de visuele instellingen wordt dan teruggegrepen op allerlei standaard waarden. Dat ziet er zo uit.

# Het maken van de grafiek
grafiek <- ggplot(fake_news_label, aes(x = DATUM, y = BEZOEKERS, label = LABEL)) +
  geom_area()

# Het resultaat
grafiek

Aanpassingen

Dit ziet er al leuk uit, maar laten we eerlijk zijn: not even close… Wat er opvalt aan de grafiek in vergelijking met het origineel:

  • Allerlei kleuren kloppen niet
  • Ook is er geen sprake van doorzichtigheid van de vulling
  • De weergave van de dagen is anders (‘Feb 02’ versus ‘29-01’)
  • Niet alle dagen staan op de x-as
  • De verdeling op de y-as is anders
  • De namen van de gebruikte variabelen per as worden in het origineel niet weergegeven
  • De opvulling raakt de x-as en de y-as niet
  • Er mist een annotatie met het aantal bezoekers op 4 februari
  • De verhoudingen kloppen niet

Kleuren

Zoals gezegd zijn er enorm veel mogelijkheden om de grafiek aan te passen. Hieronder passen we in enkele logische stappen onze grafiek aan. Te beginnen met de kleuren!

# We maken een nieuwe grafiek (grafiek_2)
grafiek_2 <- ggplot(fake_news_label, aes(x = DATUM, y = BEZOEKERS, label = LABEL)) +
  
  # We zetten 'size' op 0, dat is de omlijning van de opvulling, de kleur van de opvulling is 'fill'
  geom_area(size = 0, fill = "#187DC0", alpha = .2) +
  
  # Met geom_line voegen we een lijn toe die de waarden uit de tabel volgt en mooi aansluit op de opvulling
  geom_line(size = 1, color = "#187DC0")

# Het resultaat
grafiek_2


Assen

Dat ziet er al een stuk beter uit! Een mooie volgende stap is het aanpassen van de waarden op de assen. Ook kunnen we gelijk zorgen dat de grafiek mooi op de assen ‘rust’, in plaats van erboven zweeft.

# We maken onze derde grafiek
grafiek_3 <- grafiek_2 + 
  
  # We passen de waarden op de x-as aan, met een datum voor elke dag en een andere formulering
  scale_x_date(date_breaks = "1 day",
               date_labels = "%d-%m",
               expand = c(0, 0)) +
  
  # Ook voor de y-as voeren we de gewenste veranderingen door
  scale_y_continuous(limits = c(0, 570),
                     breaks = seq(0, 560, 56),
                     expand = c(0, 0))

# Het resultaat
grafiek_3


Thema

Een deel van de wijzigingen die we nu nog door moeten voeren kunnen we doen door een eigen thema aan te maken. In het thema kan je allerlei zaken bepalen, zoals de achtergrondkleur van de grafiek en de weergave van de titels van de assen (bij ons BEZOEKERS en DATUM).

# We maken het thema aan als een functie
theme_fake <- function(...) {
  
  # We halen allereerst de titels weg
  theme(axis.title.x = element_blank(),
        axis.title.y = element_blank(),
        
        # We maken de achtergrond van de grafiek wit
        panel.background = element_rect(fill = "#FFFFFF",
                                        color = NA),
        
        # We maken de lijnen door de grafiek grijs
        panel.grid.major = element_line(color = "#E8E8E8", size = 0.5),
        
        # We geven een beetje meer marge mee 
        plot.margin = unit(c(.5, 1, .5, .5), "cm"),
        
        # De kleur van de lijntjes bij de waarden is nog zwart, die maken we ook grijs
        axis.ticks = element_line(color = "#E8E8E8"),
        
        # We maken de lijntjes iets langer
        axis.ticks.length = unit(.2, "cm"),
        ...
  )
}

# Nieuwe grafiek met ons thema
grafiek_4 <- grafiek_3 +
  theme_fake()

# Het resultaat
grafiek_4


Annotatie

Allright, dat begint al ergens op te lijken! Er zijn nog twee zaken die onze ‘fake news’ grafiek kunnen ontmaskeren: de grootte en het label. De grootte passen we aan tijdens het opslaan, maar ik zal hieronder alvast laten zien hoe het resultaat eruit komt te zien. Het label is wat ingewikkelder en bestaat uit twee elementen.

  • Een zwart vakje met tekst erin
  • Een pijl bovenop het vakje

De oplossing hieronder is zoals ze wel eens zeggen een beetje ‘hacky’, maar het werkt!

# We geven enkele waarden op om de locatie en de richting van de pijl mee te bepalen
pijl_datum <- as.Date("2020-02-04")
pijl_start <- 500
pijl_einde <- 515

# We maken weer een nieuwe grafiek
grafiek_5 <- grafiek_4 +
  
  # We maken de pijl
  geom_segment(aes(x = pijl_datum, 
                   y = pijl_start, 
                   xend = pijl_datum, 
                   yend = pijl_einde),
               arrow = arrow(length = unit(0.3, "cm"),
                             type = "closed")) +
  
  # We maken het label
  geom_label_repel(fill = "#222222", 
                   color = "white",
                   size = 3.8,
                   box.padding = .6,
                   label.padding = .4,
                   label.r = .3, # Dit zorgt voor mooie afronding van de randen van het label
                   label.size = NA, # Dit is de omlijsting van het label, standaard een wit randje
                   segment.color = NA) # Dit is een lijntje dat op het bijbehorende punt uitkomt

# Het resultaat
grafiek_5


Resultaat

Ik zeg het gewoon: PERFECTION! Nou, niet helemaal natuurlijk. Maar het is gelijkend genoeg om overtuigend te zijn. Om het af te ronden slaan we onze grafiek op als een .jpg en vergelijken we onze ‘fake’ versie met het origineel!

ggsave(grafiek_5, filename = "fake_news_ggplot.jpg", width = 7.3, height = 2.5, type = "cairo")


Allereerst het origineel:


En dan de zelfgemaakte ‘fake’ versie: