web-dev-qa-db-fra.com

Comment pouvons-nous créer des graphes de style xkcd?

Apparemment, les gens ont compris comment faire xkcd graphes de style 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 poignet (et comme cela est montré plus élégamment ci-dessous) dans ggplot2, l'ajout de l'argument de la gigue à une ligne permet d'obtenir un superbe aspect dessiné à la main. Alors -

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

C'est un bon exemple, mais les axes et les polices semblent plus compliqués. Les polices semblent résolues (ci-dessous), cependant. Est-ce que la seule façon de traiter les axes pour les effacer et les attirer à la main? Y a-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 jitter?

668
jebyrnes

Vous voudrez peut-être envisager le package suivant:

Package xkcd : Traçage de graphiques ggplot2 dans un style XKCD.

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

Quelques exemples (Nuages ​​de points, graphiques en barres):

  • Nuage de points:

Scatterplot

  • Diagramme à bandes:

Bar Chart

412

Pensant dans le même sens que certaines des autres réponses, j’ai "non décomposé" le graphique et ajouté la flexibilité des emplacements des étiquettes de l’axe des abscisses (ce qui semble être courant dans xkcd) et une étiquette arbitraire sur la 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é manuellement dans le répertoire de travail.

enter image description here

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)
212
Mark Bulling

Fonction de dessin de ligne 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:

Example chart

187
user295691

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

Comme indiqué ci-dessus, il existe un forum de discussion sur les polices sur le site xkcd : J'ai saisi le premier que j'ai trouvé, il peut y avoir d'autres options (meilleures?) (@Jebyrnes poste un autre code source pour les polices possibles dans 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 les remplaçant par URL appropriées pour xkcdFontURL ci-dessous; vous devrez peut-être travailler un peu plus fort pour récupérer les liens posté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 devriez le placer dans un répertoire de polices système standard.)

   library(extrafont)

Les informations les plus utiles sur les polices étaient sur le site extrafont github - cela est pris à partir de là

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

Exemple pris plus ou moins mot pour mot sur le 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")

enter image description here

136
Ben Bolker

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

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

Pour générer cette parcelle Bar plot proxy for 'Dangers at Work'

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)
32
d2a2d

C'est un début très difficile et ne couvre que (partiellement) l'aspect dessiné à la main des lignes. Cela nécessiterait un peu de travail pour automatiser cela, mais l'ajout d'un peu de bruit AR (1) à la fonction de réponse pourrait donner l'impression qu'il était 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)
14
Dason

Voici ma prise sur les lignes avec ggplot2 en utilisant 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())

Vous ne savez pas comment remplacer les axes, mais vous pouvez utiliser la même approche avec jitter. Ensuite, il suffit d'importer la police de XKCD et de la superposer avec geom_text.

13
jslefche