How to add texture to fill colors in ggplot2

前端 未结 8 1200
误落风尘
误落风尘 2020-11-22 08:30

I\'m currently using scale_brewer() for fill and these look beautiful in color (on screen and via color printer) but print relatively uniformly as greys when us

相关标签:
8条回答
  • 2020-11-22 09:28

    Hey folks here's a wee hack that addresses the texture issue in a very basic fashion:

    ggplot2: make the border on one bar darker than the others using R

    EDIT: I've finally found time to give a brief example of this hack that allows at least 3 types of basic pattern in ggplot2. The code:

    Example.Data<- data.frame(matrix(vector(), 0, 3, dimnames=list(c(), c("Value", "Variable", "Fill"))), stringsAsFactors=F)
    
    Example.Data[1, ] <- c(45, 'Horizontal Pattern','Horizontal Pattern' )
    Example.Data[2, ] <- c(65, 'Vertical Pattern','Vertical Pattern' )
    Example.Data[3, ] <- c(89, 'Mesh Pattern','Mesh Pattern' )
    
    
    HighlightDataVert<-Example.Data[2, ]
    HighlightHorizontal<-Example.Data[1, ]
    HighlightMesh<-Example.Data[3, ]
    HighlightHorizontal$Value<-as.numeric(HighlightHorizontal$Value)
    Example.Data$Value<-as.numeric(Example.Data$Value)
    
    HighlightDataVert$Value<-as.numeric(HighlightDataVert$Value)
    HighlightMesh$Value<-as.numeric(HighlightMesh$Value)
    HighlightHorizontal$Value<-HighlightHorizontal$Value-5
    HighlightHorizontal2<-HighlightHorizontal
    HighlightHorizontal2$Value<-HighlightHorizontal$Value-5
    HighlightHorizontal3<-HighlightHorizontal2
    HighlightHorizontal3$Value<-HighlightHorizontal2$Value-5
    HighlightHorizontal4<-HighlightHorizontal3
    HighlightHorizontal4$Value<-HighlightHorizontal3$Value-5
    HighlightHorizontal5<-HighlightHorizontal4
    HighlightHorizontal5$Value<-HighlightHorizontal4$Value-5
    HighlightHorizontal6<-HighlightHorizontal5
    HighlightHorizontal6$Value<-HighlightHorizontal5$Value-5
    HighlightHorizontal7<-HighlightHorizontal6
    HighlightHorizontal7$Value<-HighlightHorizontal6$Value-5
    HighlightHorizontal8<-HighlightHorizontal7
    HighlightHorizontal8$Value<-HighlightHorizontal7$Value-5
    
    HighlightMeshHoriz<-HighlightMesh
    HighlightMeshHoriz$Value<-HighlightMeshHoriz$Value-5
    HighlightMeshHoriz2<-HighlightMeshHoriz
    HighlightMeshHoriz2$Value<-HighlightMeshHoriz2$Value-5
    HighlightMeshHoriz3<-HighlightMeshHoriz2
    HighlightMeshHoriz3$Value<-HighlightMeshHoriz3$Value-5
    HighlightMeshHoriz4<-HighlightMeshHoriz3
    HighlightMeshHoriz4$Value<-HighlightMeshHoriz4$Value-5
    HighlightMeshHoriz5<-HighlightMeshHoriz4
    HighlightMeshHoriz5$Value<-HighlightMeshHoriz5$Value-5
    HighlightMeshHoriz6<-HighlightMeshHoriz5
    HighlightMeshHoriz6$Value<-HighlightMeshHoriz6$Value-5
    HighlightMeshHoriz7<-HighlightMeshHoriz6
    HighlightMeshHoriz7$Value<-HighlightMeshHoriz7$Value-5
    HighlightMeshHoriz8<-HighlightMeshHoriz7
    HighlightMeshHoriz8$Value<-HighlightMeshHoriz8$Value-5
    HighlightMeshHoriz9<-HighlightMeshHoriz8
    HighlightMeshHoriz9$Value<-HighlightMeshHoriz9$Value-5
    HighlightMeshHoriz10<-HighlightMeshHoriz9
    HighlightMeshHoriz10$Value<-HighlightMeshHoriz10$Value-5
    HighlightMeshHoriz11<-HighlightMeshHoriz10
    HighlightMeshHoriz11$Value<-HighlightMeshHoriz11$Value-5
    HighlightMeshHoriz12<-HighlightMeshHoriz11
    HighlightMeshHoriz12$Value<-HighlightMeshHoriz12$Value-5
    HighlightMeshHoriz13<-HighlightMeshHoriz12
    HighlightMeshHoriz13$Value<-HighlightMeshHoriz13$Value-5
    HighlightMeshHoriz14<-HighlightMeshHoriz13
    HighlightMeshHoriz14$Value<-HighlightMeshHoriz14$Value-5
    HighlightMeshHoriz15<-HighlightMeshHoriz14
    HighlightMeshHoriz15$Value<-HighlightMeshHoriz15$Value-5
    HighlightMeshHoriz16<-HighlightMeshHoriz15
    HighlightMeshHoriz16$Value<-HighlightMeshHoriz16$Value-5
    HighlightMeshHoriz17<-HighlightMeshHoriz16
    HighlightMeshHoriz17$Value<-HighlightMeshHoriz17$Value-5
    
    ggplot(Example.Data, aes(x=Variable, y=Value, fill=Fill)) + theme_bw() + #facet_wrap(~Product, nrow=1)+ #Ensure theme_bw are there to create borders
      theme(legend.position = "none")+
      scale_fill_grey(start=.4)+
      #scale_y_continuous(limits = c(0, 100), breaks = (seq(0,100,by = 10)))+
      geom_bar(position=position_dodge(.9), stat="identity", colour="black", legend = FALSE)+
      geom_bar(data=HighlightDataVert, position=position_dodge(.9), stat="identity", colour="black", size=.5, width=0.80)+
    geom_bar(data=HighlightDataVert, position=position_dodge(.9), stat="identity", colour="black", size=.5, width=0.60)+  
      geom_bar(data=HighlightDataVert, position=position_dodge(.9), stat="identity", colour="black", size=.5, width=0.40)+
      geom_bar(data=HighlightDataVert, position=position_dodge(.9), stat="identity", colour="black", size=.5, width=0.20)+
      geom_bar(data=HighlightDataVert, position=position_dodge(.9), stat="identity", colour="black", size=.5, width=0.0) +
      geom_bar(data=HighlightHorizontal, position=position_dodge(.9), stat="identity", colour="black", size=.5)+
      geom_bar(data=HighlightHorizontal2, position=position_dodge(.9), stat="identity", colour="black", size=.5)+
      geom_bar(data=HighlightHorizontal3, position=position_dodge(.9), stat="identity", colour="black", size=.5)+
      geom_bar(data=HighlightHorizontal4, position=position_dodge(.9), stat="identity", colour="black", size=.5)+
      geom_bar(data=HighlightHorizontal5, position=position_dodge(.9), stat="identity", colour="black", size=.5)+
      geom_bar(data=HighlightHorizontal6, position=position_dodge(.9), stat="identity", colour="black", size=.5)+
      geom_bar(data=HighlightHorizontal7, position=position_dodge(.9), stat="identity", colour="black", size=.5)+
      geom_bar(data=HighlightHorizontal8, position=position_dodge(.9), stat="identity", colour="black", size=.5)+
      geom_bar(data=HighlightMesh, position=position_dodge(.9), stat="identity", colour="black", size=.5, width=0.80)+
     geom_bar(data=HighlightMesh, position=position_dodge(.9), stat="identity", colour="black", size=.5, width=0.60)+
      geom_bar(data=HighlightMesh, position=position_dodge(.9), stat="identity", colour="black", size=.5, width=0.40)+
      geom_bar(data=HighlightMesh, position=position_dodge(.9), stat="identity", colour="black", size=.5, width=0.20)+
      geom_bar(data=HighlightMesh, position=position_dodge(.9), stat="identity", colour="black", size=.5, width=0.0)+
      geom_bar(data=HighlightMeshHoriz, position=position_dodge(.9), stat="identity", colour="black", size=.5, fill = "transparent")+
    geom_bar(data=HighlightMeshHoriz2, position=position_dodge(.9), stat="identity", colour="black", size=.5, fill = "transparent")+
      geom_bar(data=HighlightMeshHoriz3, position=position_dodge(.9), stat="identity", colour="black", size=.5, fill = "transparent")+
      geom_bar(data=HighlightMeshHoriz4, position=position_dodge(.9), stat="identity", colour="black", size=.5, fill = "transparent")+
      geom_bar(data=HighlightMeshHoriz5, position=position_dodge(.9), stat="identity", colour="black", size=.5, fill = "transparent")+
      geom_bar(data=HighlightMeshHoriz6, position=position_dodge(.9), stat="identity", colour="black", size=.5, fill = "transparent")+
      geom_bar(data=HighlightMeshHoriz7, position=position_dodge(.9), stat="identity", colour="black", size=.5, fill = "transparent")+
      geom_bar(data=HighlightMeshHoriz8, position=position_dodge(.9), stat="identity", colour="black", size=.5, fill = "transparent")+
      geom_bar(data=HighlightMeshHoriz9, position=position_dodge(.9), stat="identity", colour="black", size=.5, fill = "transparent")+
      geom_bar(data=HighlightMeshHoriz10, position=position_dodge(.9), stat="identity", colour="black", size=.5, fill = "transparent")+
      geom_bar(data=HighlightMeshHoriz11, position=position_dodge(.9), stat="identity", colour="black", size=.5, fill = "transparent")+
      geom_bar(data=HighlightMeshHoriz12, position=position_dodge(.9), stat="identity", colour="black", size=.5, fill = "transparent")+
      geom_bar(data=HighlightMeshHoriz13, position=position_dodge(.9), stat="identity", colour="black", size=.5, fill = "transparent")+
      geom_bar(data=HighlightMeshHoriz14, position=position_dodge(.9), stat="identity", colour="black", size=.5, fill = "transparent")+
      geom_bar(data=HighlightMeshHoriz15, position=position_dodge(.9), stat="identity", colour="black", size=.5, fill = "transparent")+
      geom_bar(data=HighlightMeshHoriz16, position=position_dodge(.9), stat="identity", colour="black", size=.5, fill = "transparent")+
      geom_bar(data=HighlightMeshHoriz17, position=position_dodge(.9), stat="identity", colour="black", size=.5, fill = "transparent")
    

    Produces this:

    enter image description here

    It isn't super pretty but it is the only solution I can think on.

    As can be seen I produce some very basic data. To get the vertical lines I simply create a data frame to contain the variable I wanted to add vertical lines to and redrew the graph borders multiple times reducing the width each time.

    A similar thing is done for the horizontal lines but a new data frame is needed for each redraw where I have subtracted a value (in my example '5') from the value associated with the variable of interest. Effectively lowering the height of the bar. This is clunky to achieve and there may be more streamlined approaches but this illustrates how it can be achieved.

    The mesh pattern is a combination of both. Firstly draw the vertical lines and then add the horizontal lines setting fill as fill='transparent' to ensure the vertical lines are not drawn over.

    Until there is a pattern update I hope some of you find this useful.

    EDIT 2:

    Additionally diagonal patterns may also be added. I added an extra variable to the data frame:

    Example.Data[4,] <- c(20, 'Diagonal Pattern','Diagonal Pattern' )
    

    Then I created a new data frame to hold coordinates for the diagonal lines:

    Diag <- data.frame(
      x = c(1,1,1.45,1.45), # 1st 2 values dictate starting point of line. 2nd 2 dictate width. Each whole = one background grid
      y = c(0,0,20,20),
      x2 = c(1.2,1.2,1.45,1.45), # 1st 2 values dictate starting point of line. 2nd 2 dictate width. Each whole = one background grid
      y2 = c(0,0,11.5,11.5),# inner 2 values dictate height of horizontal line. Outer: vertical edge lines.
      x3 = c(1.38,1.38,1.45,1.45), # 1st 2 values dictate starting point of line. 2nd 2 dictate width. Each whole = one background grid
      y3 = c(0,0,3.5,3.5),# inner 2 values dictate height of horizontal line. Outer: vertical edge lines.
      x4 = c(.8,.8,1.26,1.26), # 1st 2 values dictate starting point of line. 2nd 2 dictate width. Each whole = one background grid
      y4 = c(0,0,20,20),# inner 2 values dictate height of horizontal line. Outer: vertical edge lines.
      x5 = c(.6,.6,1.07,1.07), # 1st 2 values dictate starting point of line. 2nd 2 dictate width. Each whole = one background grid
      y5 = c(0,0,20,20),# inner 2 values dictate height of horizontal line. Outer: vertical edge lines.
      x6 = c(.555,.555,.88,.88), # 1st 2 values dictate starting point of line. 2nd 2 dictate width. Each whole = one background grid
      y6 = c(6,6,20,20),# inner 2 values dictate height of horizontal line. Outer: vertical edge lines.
      x7 = c(.555,.555,.72,.72), # 1st 2 values dictate starting point of line. 2nd 2 dictate width. Each whole = one background grid
      y7 = c(13,13,20,20),# inner 2 values dictate height of horizontal line. Outer: vertical edge lines.
      x8 = c(.8,.8,1.26,1.26), # 1st 2 values dictate starting point of line. 2nd 2 dictate width. Each whole = one background grid
      y8 = c(0,0,20,20),# inner 2 values dictate height of horizontal line. Outer: vertical edge lines.
      #Variable = "Diagonal Pattern",
      Fill = "Diagonal Pattern"
      )
    

    From there I added geom_paths to the ggplot above with each one calling different coordinates and drawing the lines over the desired bar:

    +geom_path(data=Diag, aes(x=x, y=y),colour = "black")+  # calls co-or for sig. line & draws
      geom_path(data=Diag, aes(x=x2, y=y2),colour = "black")+  # calls co-or for sig. line & draws
      geom_path(data=Diag, aes(x=x3, y=y3),colour = "black")+
      geom_path(data=Diag, aes(x=x4, y=y4),colour = "black")+
      geom_path(data=Diag, aes(x=x5, y=y5),colour = "black")+
      geom_path(data=Diag, aes(x=x6, y=y6),colour = "black")+
      geom_path(data=Diag, aes(x=x7, y=y7),colour = "black")
    

    This results in the following:

    enter image description here

    It is a bit sloppy as I didn't invest too much time in getting the lines perfectly angled and spaced apart but this should serve as a proof of concept.

    Obviously the lines can lean the opposite direction and there is also room for diagonal meshing much like the horizontal and vertical meshing.

    I think that's about all I can offer on the pattern front. Hope someone can find a use for it.

    EDIT 3: Famous last words. I have come up with another pattern option. This time using geom_jitter.

    Again I added another Variable to the data frame:

    Example.Data[5,] <- c(100, 'Bubble Pattern','Bubble Pattern' )
    

    And I ordered how I wanted each pattern presented:

    Example.Data$Variable = Relevel(Example.Data$Variable, ref = c("Diagonal Pattern", "Bubble Pattern","Horizontal Pattern","Mesh Pattern","Vertical Pattern"))
    

    Next I created a column to contain the number associated with the intended target bar on the x-axis:

    Example.Data$Bubbles <- 2
    

    Followed by columns to contain the positions on the y-axis of the 'bubbles':

    Example.Data$Points <- c(5, 10, 15, 20, 25)
    Example.Data$Points2 <- c(30, 35, 40, 45, 50)
    Example.Data$Points3 <- c(55, 60, 65, 70, 75)
    Example.Data$Points4 <- c(80, 85, 90, 95, 7)
    Example.Data$Points5 <- c(14, 21, 28, 35, 42)
    Example.Data$Points6 <- c(49, 56, 63, 71, 78)
    Example.Data$Points7 <- c(84, 91, 98, 6, 12)
    

    Finally I added geom_jitters to the ggplot above using the new columns for positioning and re-using 'Points' to vary the size of the 'bubbles':

    +geom_jitter(data=Example.Data,aes(x=Bubbles, y=Points, size=Points), alpha=.5)+
      geom_jitter(data=Example.Data,aes(x=Bubbles, y=Points2, size=Points), alpha=.5)+
      geom_jitter(data=Example.Data,aes(x=Bubbles, y=Points, size=Points), alpha=.5)+
      geom_jitter(data=Example.Data,aes(x=Bubbles, y=Points2, size=Points), alpha=.5)+
      geom_jitter(data=Example.Data,aes(x=Bubbles, y=Points3, size=Points), alpha=.5)+
      geom_jitter(data=Example.Data,aes(x=Bubbles, y=Points4, size=Points), alpha=.5)+
      geom_jitter(data=Example.Data,aes(x=Bubbles, y=Points, size=Points), alpha=.5)+
      geom_jitter(data=Example.Data,aes(x=Bubbles, y=Points2, size=Points), alpha=.5)+
      geom_jitter(data=Example.Data,aes(x=Bubbles, y=Points, size=Points), alpha=.5)+
      geom_jitter(data=Example.Data,aes(x=Bubbles, y=Points2, size=Points), alpha=.5)+
      geom_jitter(data=Example.Data,aes(x=Bubbles, y=Points3, size=Points), alpha=.5)+
      geom_jitter(data=Example.Data,aes(x=Bubbles, y=Points4, size=Points), alpha=.5)+
      geom_jitter(data=Example.Data,aes(x=Bubbles, y=Points2, size=Points), alpha=.5)+
      geom_jitter(data=Example.Data,aes(x=Bubbles, y=Points5, size=Points), alpha=.5)+
      geom_jitter(data=Example.Data,aes(x=Bubbles, y=Points5, size=Points), alpha=.5)+
      geom_jitter(data=Example.Data,aes(x=Bubbles, y=Points6, size=Points), alpha=.5)+
      geom_jitter(data=Example.Data,aes(x=Bubbles, y=Points6, size=Points), alpha=.5)+
      geom_jitter(data=Example.Data,aes(x=Bubbles, y=Points7, size=Points), alpha=.5)+
      geom_jitter(data=Example.Data,aes(x=Bubbles, y=Points7, size=Points), alpha=.5)+
      geom_jitter(data=Example.Data,aes(x=Bubbles, y=Points, size=Points), alpha=.5)+
      geom_jitter(data=Example.Data,aes(x=Bubbles, y=Points2, size=Points), alpha=.5)+
      geom_jitter(data=Example.Data,aes(x=Bubbles, y=Points, size=Points), alpha=.5)+
      geom_jitter(data=Example.Data,aes(x=Bubbles, y=Points2, size=Points), alpha=.5)+
      geom_jitter(data=Example.Data,aes(x=Bubbles, y=Points3, size=Points), alpha=.5)+
      geom_jitter(data=Example.Data,aes(x=Bubbles, y=Points4, size=Points), alpha=.5)+
      geom_jitter(data=Example.Data,aes(x=Bubbles, y=Points, size=Points), alpha=.5)+
      geom_jitter(data=Example.Data,aes(x=Bubbles, y=Points2, size=Points), alpha=.5)+
      geom_jitter(data=Example.Data,aes(x=Bubbles, y=Points, size=Points), alpha=.5)+
      geom_jitter(data=Example.Data,aes(x=Bubbles, y=Points2, size=Points), alpha=.5)+
      geom_jitter(data=Example.Data,aes(x=Bubbles, y=Points3, size=Points), alpha=.5)+
      geom_jitter(data=Example.Data,aes(x=Bubbles, y=Points4, size=Points), alpha=.5)+
      geom_jitter(data=Example.Data,aes(x=Bubbles, y=Points2, size=Points), alpha=.5)+
      geom_jitter(data=Example.Data,aes(x=Bubbles, y=Points5, size=Points), alpha=.5)+
      geom_jitter(data=Example.Data,aes(x=Bubbles, y=Points5, size=Points), alpha=.5)+
      geom_jitter(data=Example.Data,aes(x=Bubbles, y=Points6, size=Points), alpha=.5)+
      geom_jitter(data=Example.Data,aes(x=Bubbles, y=Points6, size=Points), alpha=.5)+
      geom_jitter(data=Example.Data,aes(x=Bubbles, y=Points7, size=Points), alpha=.5)+
      geom_jitter(data=Example.Data,aes(x=Bubbles, y=Points7, size=Points), alpha=.5)
    

    Each time the plot is run the jitter positions the 'bubbles' differently but here is one of the nicer outputs I had:

    enter image description here

    Sometimes the 'bubbles' will jitter outside borders. If this happens rerun or simply export in larger dimensions. More bubbles can be plotted on each increment on the y-axis which will fill more of the blank space if you so desire.

    That makes up to 7 patterns (if you include opposite leaning diagonal lines and diagonal mesh of both) that can be hacked in ggplot.

    Please feel free to suggest more if anyone can think on some.

    EDIT 4: I've been working on a wrapper function to automate hatching/patterns in ggplot2. I'll post a link once I've expanded the function to allow patterns in facet_grid plots etc. Here's an output with the function input for a simple plot of bars as an example:

    I'll add one last edit once I have the function ready to share.

    EDIT 5: Here's a link to the function EggHatch that I wrote to make the process of adding patterns to geom_bar plots a little easier.

    0 讨论(0)
  • 2020-11-22 09:29

    ggplot can use colorbrewer palettes. Some of these are "photocopy" friendly. So mabe something like this will work for you?

    ggplot(diamonds, aes(x=cut, y=price, group=cut))+
    geom_boxplot(aes(fill=cut))+scale_fill_brewer(palette="OrRd")
    

    in this case OrRd is a palette found on the colorbrewer webpage: http://colorbrewer2.org/

    Photocopy Friendly: This indicates that a given color scheme will withstand black and white photocopying. Diverging schemes can not be photocopied successfully. Differences in lightness should be preserved with sequential schemes.

    0 讨论(0)
提交回复
热议问题