Comment pouvons-nous faire des graphiques de style xkcd?

697

Apparemment, les gens ont compris comment créer des graphiques de style xkcd dans Mathematica et dans LaTeX . Pouvons-nous le faire en R? Ggplot2-ers? Un geom_xkcd et / ou theme_xkcd?

Je suppose que dans les graphiques de base, par (xkcd = TRUE)? Comment fait-on ça?

xkcd # 1064

En tant que premier coup de couteau (et comme beaucoup plus élégamment illustré ci-dessous) dans ggplot2, l'ajout de l'argument de gigue à une ligne donne un superbe look dessiné à la main. Donc -

ggplot(mapping=aes(x=seq(1,10,.1), y=seq(1,10,.1))) + 
  geom_line(position="jitter", color="red", size=2) + theme_bw()

Cela donne un bel exemple - mais les axes et les polices semblent plus délicats. Les polices semblent cependant résolues (ci-dessous). Est-ce la seule façon de gérer les axes pour les masquer et les dessiner à la main? Existe-t-il une solution plus élégante? En particulier, dans ggplot2, element_line dans le nouveau système de thèmes peut-il être modifié pour prendre un argument de type gigue?

jebyrnes
la source
8
quels éléments considérez-vous exactement comme des éléments nécessaires des graphiques xkcd? des annotations? courbes, axes et échelles arbitraires? look and feel dessiné à la main?
smcg
8
Je me concentrerais sur l'aspect et la sensation dessinés à la main, de tous les éléments du graphique: axes, texte, lignes, etc.
joran
61
N'oubliez pas la souris obligatoire sur!
Jørgen R
4
De plus, les polices sont prises en charge par xkcdsucks.blogspot.com/2009/03/…
jebyrnes
11
Tout comme j'aime R et xkcd, qui a jamais commencé ce meme devrait avoir la tête trempée. Utilisez un crayon , les gens!
naught101

Réponses:

424

Vous pouvez envisager le package suivant:

Package xkcd : traçage des graphiques ggplot2 dans un style XKCD.

library(xkcd)
vignette("xkcd-intro")

Quelques exemples (diagrammes de dispersion, graphiques à barres):

  • Nuage de points:

Nuage de points

  • Diagramme à bandes:

Diagramme à bandes

Emilio Torres Manzanera
la source
@smillig, à partir du fichier ReadMe de Windows r-release : "Les packages binaires seront disponibles sur CRAN environ 1 à 3 jours après la publication des sources."
GSee
43
Que dois-je citer lors de l'utilisation du package dans des publications?
ziggystar
1
+1 Et merci pour le super package. J'ai du mal à installer les polices ! Une correction dans le fichier d'introduction, (sec-2.1, ligne 5, .tff -> .ttf). Un autre encore en attente !!
Shambho
1
Excellent travail, j'aime beaucoup le theme_xkcd () qui nous permet de l'utiliser très facilement. Si vous voulez l'améliorer, je suggérerais que xkcdaxis () puisse être appelé sans argument (il dessinerait simplement l'axe normal). ie ggplot (data = temp.all, aes (x = State.Code, y = Sample.Value, fill = year)) + geom_boxplot () + coord_cartesian (ylim = c (0,40)) + theme_xkcd () + xkcdaxis ()
zipp
il semble que quelque chose soit cassé. installer des xkcdœuvres, mais essayer de library(xkcd)céder > library(xkcd) Loading required package: extrafont Registering fonts with R Error in loadNamespace(j <- i[[1L]], c(lib.loc, .libPaths()), versionCheck = vI[[j]]) : there is no package called ‘acepack’ Error: package or namespace load failed for ‘xkcd’et essayer de acepackcéder> install.packages("ace") Warning in install.packages : package ‘ace’ is not available (for R version 3.2.1)
Shawn Mehan
216

En pensant dans la même ligne que certaines des autres réponses, j'ai "non-ggploté" le graphique et j'ai également ajouté la flexibilité des emplacements d'étiquette de l'axe des x (qui semble être courante dans xkcd) et une étiquette arbitraire sur le graphique.

Notez que j'ai eu quelques problèmes avec le chargement de la police Humor Sans et que je l'ai téléchargée manuellement dans le répertoire de travail.

entrez la description de l'image ici

Et le code ...

library(ggplot2)
library(extrafont)

### Already have read in fonts (see previous answer on how to do this)
loadfonts()

### Set up the trial dataset 
data <- NULL
data$x <- seq(1, 10, 0.1)
data$y1 <- sin(data$x)
data$y2 <- cos(data$x)
data$xaxis <- -1.5

data <- as.data.frame(data)

### XKCD theme
theme_xkcd <- theme(
    panel.background = element_rect(fill="white"), 
    axis.ticks = element_line(colour=NA),
    panel.grid = element_line(colour="white"),
    axis.text.y = element_text(colour=NA), 
    axis.text.x = element_text(colour="black"),
    text = element_text(size=16, family="Humor Sans")
    )

 ### Plot the chart
 p <- ggplot(data=data, aes(x=x, y=y1))+
      geom_line(aes(y=y2), position="jitter")+
      geom_line(colour="white", size=3, position="jitter")+
      geom_line(colour="red", size=1, position="jitter")+
      geom_text(family="Humor Sans", x=6, y=-1.2, label="A SIN AND COS CURVE")+
      geom_line(aes(y=xaxis), position = position_jitter(h = 0.005), colour="black")+
      scale_x_continuous(breaks=c(2, 5, 6, 9), 
      labels = c("YARD", "STEPS", "DOOR", "INSIDE"))+labs(x="", y="")+
      theme_xkcd

ggsave("xkcd_ggplot.jpg", plot=p, width=8, height=5)
Mark Bulling
la source
C'est fantastique! Maintenant, si seulement il y avait un moyen de demander à element_line de prendre un argument de gigue pour le transformer en thèmes ... cela scellerait l'accord, je pense.
jebyrnes
1
Pourrait-il y avoir un paquet manquant dans votre code, j'obtiens "Erreur: Impossible de trouver la fonction" thème "dans theme_xkcd <- theme (
Owe Jessen
1
Hm, quelle est la solution au message d'erreur alors? - Une version plus récente de ggplot2fait l'affaire.
Rico
J'ai trouvé que l'utilisation geom_smoothde method = "loess", span = 0.6, se = FALSEet position = position_jitter(h=0.005)me donnait de meilleurs résultats sur les données bruyantes, car les lignes sont à la fois lisses et instables.
zeehio
Il manque encore quelque chose? Fehler dans grid.Call (C_textBounds, as.graphicsAnnot (x $ label), x $ x, x $ y,: Polygonkante nicht gefunden Ruft auf: ggsave ... <Anonymous> -> widthDetails -> widthDetails.text -> grid .Call Zusätzlich: Warnmeldungen: 1: In grid.Call (C_textBounds, as.graphicsAnnot (x $ label), x $ x, x $ y,: Für Familie "Humor Sans" konnte kein Zeichensatz gefunden werden ... Ausführung angehalten
Coliban
189

Fonction de dessin au trait de base:

xkcd_line <- function(x, y, color) {
  len <- length(x);
  rg <- par("usr");
  yjitter <- (rg[4] - rg[3]) / 1000;
  xjitter <- (rg[2] - rg[1]) / 1000;
  x_mod <- x + rnorm(len) * xjitter;
  y_mod <- y + rnorm(len) * yjitter;
  lines(x_mod, y_mod, col='white', lwd=10);
  lines(x_mod, y_mod, col=color, lwd=5);
}

Axe de base:

xkcd_axis <- function() {
  rg <- par("usr");
  yaxis <- 1:100 / 100 * (rg[4] - rg[3]) + rg[3];
  xaxis <- 1:100 / 100 * (rg[2] - rg[1]) + rg[1];
  xkcd_line(1:100 * 0 + rg[1] + (rg[2]-rg[1])/100, yaxis,'black')
  xkcd_line(xaxis, 1:100 * 0 + rg[3] + (rg[4]-rg[3])/100, 'black')
}

Et exemple de code:

data <- data.frame(x=1:100)
data$one <- exp(-((data$x - 50)/10)^2)
data$two <- sin(data$x/10)
plot.new()
plot.window(
    c(min(data$x),max(data$x)),
    c(min(c(data$one,data$two)),max(c(data$one,data$two))))
xkcd_axis()
xkcd_line(data$x, data$one, 'red')
xkcd_line(data$x, data$two, 'blue')

Produit:

Exemple de graphique

user295691
la source
137

Voici une tentative de polices, basée sur les liens des forums xkcd et du extrafontpackage:

Comme indiqué ci-dessus, il existe un forum de discussion sur les polices sur le site xkcd : j'ai attrapé la première que j'ai pu trouver, il peut y avoir d'autres (meilleures?) Options (@jebyrnes publie une autre source pour les polices possibles dans les commentaires ci-dessus - le fichier TTF est ici ; quelqu'un a signalé une erreur 404 pour cette source, vous pouvez également essayer ici ou ici , en remplaçant ces URL de manière appropriée xkcdFontURLci-dessous; vous devrez peut-être travailler un peu plus dur pour récupérer les liens publiés par Github)

   xkcdFontURL <- "http://simonsoftware.se/other/xkcd.ttf"
   download.file(xkcdFontURL,dest="xkcd.ttf",mode="wb")

(Ceci est pour une utilisation rapide et ponctuelle: pour une utilisation régulière, vous devez le placer dans un répertoire de polices système standard.)

   library(extrafont)

Les informations les plus utiles sur les polices se trouvaient sur le site github extrafont - elles sont prises à partir de là

font_import(".")   ## because we downloaded to working directory
loadfonts()

Exemple repris plus ou moins textuellement du site github:

library(ggplot2)
p <- ggplot(mtcars, aes(x=wt, y=mpg)) + geom_point() +
  ggtitle("Fuel Efficiency of 32 Cars") +
  xlab("Weight (x1000 lb)") + ylab("Miles per Gallon") +
  theme(text=element_text(size=16, family="xkcd"))

ggsave("xkcd_ggplot.pdf", plot=p,  width=4, height=4)
## needed for Windows:
##   Sys.setenv(R_GSCMD = "C:/Program Files/gs/gs9.05/bin/gswin32c.exe")
embed_fonts("xkcd_ggplot.pdf")

entrez la description de l'image ici

Ben Bolker
la source
32

J'ai conçu un calendrier analytique sur le thème xkcd en utilisant simplement RStudio. Voici un exemple de style graphique à barres xkcd

  • Police utilisée = HumorSans.ttf [lien donné ci-dessus]
  • Paquet utilisé [xkcd]

Pour générer ce tracé Proxy graphique à barres pour «Dangers au travail»

Voici le code utilisé

#using packages xkcd, ggplot 
library(xkcd)
library(ggplot2)
font_import(pattern="[H/h]umor")
loadfonts()

### Set up the trial dataset 
d1 <- data.frame('type'=c('DROWNING','RADIATION','TOILET',"ELECTRICAL",'NOISE','PANTRY','YOUR    FALLING ON OBJECTS','OBJECTS FALLING ON YOU','BOSS','FIRE','TRAVEL TO WORK'),'score'=c(2,2,3,6,6,6,11,14,21,26,30))

# we will keep adding layers on plot p. first the bar plot
p <- NULL
p <- ggplot() + xkcdrect(aes(xmin = type-0.1,xmax= type+0.1,ymin=0,ymax =score),
                     d1,fill= "#D55E00", colour= "#D55E00")  +
     geom_text(data=d1,aes(x=type,y=score+2.5,label=score,ymax=0),family="Humor Sans") +   coord_flip()

#hand drawn axes
d1long <- NULL
d1long <- rbind(c(0,-2),d1,c(12,32))
d1long$xaxis <- -1
d1long$yaxis <- 11.75

# drawing jagged axes
p <- p + geom_line(data=d1long,aes(x=type,y=jitter(xaxis)),size=1)
p <- p + geom_line(data=d1long,aes(x=yaxis,y=score), size=1) 

# draw axis ticks and labels
p <- p +  scale_x_continuous(breaks=seq(1,11,by=1),labels = data$Type) +
     scale_y_continuous(breaks=NULL)

#writing stuff on the graph
t1 <- "GOOGLE RESULTS"
p <- p + annotate('text',family="Humor Sans", x=12.5, y=12, label=t1, size=6) 

# XKCD theme
p <- p + theme(panel.background = element_rect(fill="white"),
           panel.grid = element_line(colour="white"),axis.text.x = element_blank(), 
           axis.text.y = element_text(colour="black"),text = element_text(size=18, family="Humor   Sans") ,panel.grid.major = element_blank(),panel.grid.minor = element_blank(),panel.border = element_blank(),axis.title.y = element_blank(),axis.title.x = element_blank(),axis.ticks = element_blank())

print(p)
d2a2d
la source
14

C'est un début très, très difficile et ne couvre que (partiellement) l'aspect et la sensation dessinés à la main des lignes. Il faudrait un peu de travail pour automatiser cela, mais en ajoutant un peu de bruit AR (1) à la fonction de réponse, cela pourrait sembler légèrement dessiné à la main

set.seed(551)
x <- seq(0, 1, length.out = 1000)
y <- sin(x)

imperfect <- arima.sim(n = length(y), model = list(ar = c(.9999)))
imperfect <- scale(imperfect)
z <- y + imperfect*.005
plot(x, z, type = "l", col = "blue", lwd = 2)
Dason
la source
13

Voici ma vision des choses en ggplot2utilisant une partie du code ci-dessus:

ggplot()+geom_line(aes(x=seq(0,1,length.out=1000),y=sin(x)),position=position_jitter(width=0.02),lwd=1.5,col="white")+
  geom_line(aes(x=seq(0,1,length.out=1000),y=sin(x)),position=position_jitter(width=0.004),lwd=1.4,col="red")+
  geom_line(aes(x=seq(0,1,length.out=1000),y=cos(x)),position=position_jitter(width=0.02),lwd=1.5,col="white")+
  geom_line(aes(x=seq(0,1,length.out=1000),y=cos(x)),position=position_jitter(width=0.004),lwd=1.4,col="blue")+
  theme_bw()+theme(panel.grid.major=element_blank(),panel.grid.minor=element_blank())

Je ne sais pas comment remplacer les axes, mais je pourrais utiliser la même approche avec jitter. Il s'agit ensuite d'importer la police de XKCD et de la superposer avec geom_text.

jslefche
la source