¿Cómo podemos hacer gráficos de estilo xkcd?

697

Aparentemente, la gente ha descubierto cómo hacer gráficos de estilo xkcd en Mathematica y en LaTeX . ¿Podemos hacerlo en R? Ggplot2-ers? ¿Un geom_xkcd y / o theme_xkcd?

Supongo que en gráficos básicos, par (xkcd = TRUE)? ¿Cómo lo hago?

xkcd # 1064

Como primera puñalada (y mucho más elegantemente mostrada a continuación) en ggplot2, agregar el argumento de jitter a una línea es una gran apariencia dibujada a mano. Entonces -

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

Es un buen ejemplo, pero los ejes y las fuentes parecen más complicados. Sin embargo, las fuentes aparecen resueltas (abajo). ¿Es la única forma de lidiar con los ejes para dejarlos en blanco y dibujarlos a mano? ¿Hay una solución más elegante? En particular, en ggplot2, ¿se puede modificar element_line en el nuevo sistema de temas para tomar un argumento similar a jitter?

jebyrnes
fuente
8
¿Qué consideraría exactamente que son elementos necesarios de los gráficos xkcd? anotaciones? curvas arbitrarias, ejes y escalas? aspecto y sensación dibujados a mano?
smcg
8
Me centraría en el aspecto dibujado a mano, de todos los elementos del gráfico: ejes, texto, líneas, etc.
joran
61
¡No olvide el mouse obligatorio!
Jørgen R
44
Además, las fuentes se ocupan de xkcdsucks.blogspot.com/2009/03/…
jebyrnes
11
Por mucho que me encante R y xkcd, quien haya comenzado este meme debería tener la cabeza mojada. ¡Use un lápiz , gente!
naught101

Respuestas:

424

Es posible que desee considerar el siguiente paquete:

Paquete xkcd : Trazado de gráficos ggplot2 en un estilo XKCD.

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

Algunos ejemplos (diagramas de dispersión, gráficos de barras):

  • Gráfico de dispersión:

Gráfico de dispersión

  • Gráfico de barras:

Gráfico de barras

Emilio Torres Manzanera
fuente
@smillig, del archivo Léame de Windows r-release : "Los paquetes binarios estarán disponibles en CRAN aproximadamente 1-3 días después de que se hayan publicado las fuentes".
GSee
43
¿Qué debo citar al usar el paquete en publicaciones?
ziggystar
1
+1 Y gracias por el gran paquete. ¡Tengo problemas para instalar las fuentes ! Una corrección en el archivo de introducción, (sec-2.1, línea 5, .tff -> .ttf). ¡Otro aún pendiente!
Shambho
1
Buen trabajo, me gusta mucho el theme_xkcd () que nos permite usarlo muy fácilmente. Si desea mejorarlo, sugeriría que xkcdaxis () pueda llamarse sin argumento (solo dibujaría el eje normal). es decir, 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
Parece que algo en esto está roto. instalar xkcdobras, pero tratar de library(xkcd)rendir > 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’y tratar de obtener acepackrendimientos> install.packages("ace") Warning in install.packages : package ‘ace’ is not available (for R version 3.2.1)
Shawn Mehan
216

Pensando en la misma línea que algunas de las otras respuestas, he "desglosado" el gráfico y también he agregado la flexibilidad de las ubicaciones de las etiquetas del eje x (que parece ser común en xkcd) y una etiqueta arbitraria en el gráfico.

Tenga en cuenta que tuve algunos problemas al cargar la fuente Humor Sans y la descargué manualmente al directorio de trabajo.

ingrese la descripción de la imagen aquí

Y el código ...

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
fuente
¡Esto es fantástico! Ahora, si solo hubiera una manera de que element_line tomara un argumento de inquietud para trabajarlo en temas ... eso sellaría el trato, creo.
jebyrnes
1
¿Podría haber un paquete faltante en su código, obtengo "Error: No se pudo encontrar la función" tema "en theme_xkcd <- theme (
Owe Jessen
1
Hm, ¿cuál es la solución al mensaje de error entonces? - Una versión más nueva de ggplot2hizo el truco.
Rico
Descubrí que usar geom_smoothcon method = "loess", span = 0.6, se = FALSEy position = position_jitter(h=0.005)me estaba dando mejores resultados en datos ruidosos, ya que las líneas son suaves y fluctuantes.
zeehio
¿Todavía falta algo? Fehler en grid.Call (C_textBounds, as.graphicsAnnot (x $ label), x $ x, x $ y,: Polygonkante nicht gefunden Ruft auf: ggsave ... <Anónimo> -> 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

Función básica de dibujo lineal:

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);
}

Eje básico:

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')
}

Y código de muestra:

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')

Produce:

Gráfico de ejemplo

usuario295691
fuente
137

Aquí hay un intento de las fuentes, basado en enlaces de los foros xkcd y el extrafontpaquete:

Como se señaló anteriormente, hay una discusión en el foro sobre las fuentes en el sitio xkcd : tomé la primera que pude encontrar, puede haber otras opciones (¿mejores?) (@Jebyrnes publica otra fuente de posibles fuentes en los comentarios anteriores: el archivo TTF está aquí ; alguien informó un error 404 para esa fuente, alternativamente, puede intentar aquí o aquí , sustituyendo esas URL adecuadamente por xkcdFontURLdebajo; puede que tenga que trabajar un poco más para recuperar los enlaces publicados por Github)

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

(Esto es para uso rápido y único: para uso regular, debe colocarlo en algún directorio de fuentes del sistema estándar).

   library(extrafont)

La información más útil sobre las fuentes estaba en el sitio extrafont github ; esto se toma de allí

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

Ejemplo tomado más o menos textualmente del sitio 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")

ingrese la descripción de la imagen aquí

Ben Bolker
fuente
32

Diseñé un calendario de análisis temático xkcd simplemente usando RStudio. Aquí hay un ejemplo de estilo de diagrama de barras xkcd

  • Fuente utilizada = HumorSans.ttf [enlace proporcionado anteriormente]
  • Paquete utilizado [xkcd]

Para generar esta trama Representación gráfica de barras para 'Peligros en el trabajo'

Aquí está el código usado

#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
fuente
14

Este es un comienzo muy, muy difícil y solo cubre (parcialmente) el aspecto dibujado a mano de las líneas. Se necesitaría un poco de trabajo para automatizar esto, pero agregar algo de ruido AR (1) a la función de respuesta podría hacer que parezca un poco dibujado a mano.

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)
Razón
fuente
13

Aquí está mi opinión sobre el ggplot2uso de algunos de los códigos de arriba:

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())

No estoy seguro de cómo reemplazar los ejes, pero podría usar el mismo enfoque con jitter. Entonces es cuestión de importar la fuente desde XKCD y aplicar capas geom_text.

jslefche
fuente