Manual legend in ggraph/ggplot2 [R]
Asked Answered
D

0

6

Apart from this post, here I am asking new questions how to make adjustment in legends built by ggraph.

Here are scripts to produce current plot:

    ## Packages
    library(igraph)
    library(tidygraph)
    library(ggraph)
    library(ggplot2)
    library(tidyverse)

    ## Edge and node
    edge <- data.frame(from=c(0,0,0,0,1,2,3),
                       to=c(0,1,2,3,0,0,0),
                       weight=c(1,3,1,1,3,1,1))
    node <- data.frame(id=c(0,1,2,3),
                       p=c(9,1,0,0),
                       w=c(0,2,0,0),
                       s=c(0,1,1,1),
                       size=c(9,3,1,1),
                       gr=c(0,1,1,2))

    ## Load data frames as tbl_graph class
    edge <- edge %>% mutate(from=from+1,to=to+1)
    net <- tbl_graph(nodes=node,edges=edge,directed=TRUE)

    ## Set arrows
    ar <- arrow(angle=30,length=unit(5,"mm"),ends="last",type="closed")
    ## Plot
    ggraph(net,layout="graphopt") +
    ## Edges
    geom_edge_link(aes(start_cap=circle(log(node1.size)+2,unit="native"),
                       end_cap=circle(log(node2.size)+2,unit="native"),
                       width=weight,label=weight),
        position="identity",angle_calc="along",force_flip=TRUE,
        label_dodge=unit(4.0,"mm"),label_push=unit(-0.4,"mm")) +
        ## Width scale
        scale_edge_width(range=c(0.4,4),breaks=c(1:10),name="Movements\nbetween zones") +
    ## Add arrows separately
    geom_edge_link(arrow=ar,aes(start_cap=circle(log(node1.size)+1,unit="native"),
        end_cap=circle(log(node2.size)+1,unit="native"))) +
    ## Nodes
        ## Plot location id
        geom_node_label(aes(label=id,hjust=log(size+6),vjust=log(size+6)),repel=TRUE,
                        label.padding=unit(0.8,"mm"),label.r=unit(0.0,"mm"),label.size=0.1,size=3.5) +
        ## Circle
        geom_node_circle(aes(r=log(size)+1),color="black",fill="white",size=0.4) +
        ## Plot work activity
        geom_node_text(aes(size=w,hjust=log(w)+0.4),label="w",color="red",
                       position="identity",vjust=0.4,fontface="bold") +
        ## Plot school activity
        geom_node_text(aes(size=s,hjust=-log(s)-0.2),label="s",color="blue",
                       position="identity",vjust=0.4,fontface="bold") +
        ## Size scale
        scale_size(range=c(0,5),breaks=c(1:100),name="Numberof\nActivities",
                   guide=guide_legend(override.aes=list(label="a",color="black"))) +
        # scale_color() +
    ## Theme
    theme_graph() + coord_fixed()

This is my desired result.

enter image description here

This is the result from above scripts.

enter image description here

There are two issues related to legend to reach my desired result:

  • How can I replace overlapped "w" and "s" in "Number of Activities" by other font, such as "a" (activity) in black as shown in desired result?
  • How can I add one more manual legend "Types of activity" shown in desired result?

Though it is written in ggraph, I suppose the grammar seems to be similar to that in ggplot2. I appreciate your suggestions!!

========== UPDATE ==========

The first issue has solved by changing scale_size argument as shown in updated scripts.

However, the second issue is still remaining and I found one more issue on 0-value symbols at the center of circles (very small dot). I have found some solutions to solve the issue by applying 1) subset() to omit 0-value records from data frame in data=subset(df,x!=0), 2) simply filling 0 value by NA in data=ifelse(x==0,NA,.) methods, however as it is written from graph object, it may not work for this case straightforward.

========== UPDATE ver.2 ==========

It is really tricky but somehow I could remove dots at the center of line as well as adding one legend.

I am really not sure the reason but the former issue was solved by 1) replacing 0 values in node data frame by NA, 2) replace NA in aes(size=...) statement in geom_node_text as aes(size=ifelse(is.na(w),0,w) ..., then 3) specify color by color=ifelse(w==0,"white","red"). It does not remove the data but just change color of 0-value into white to make it invisible.

I suppose it is not formal solution but only the way that I encountered during dozens of trials. Interesting thing is that 1) and 2) should be combined otherwise it returns an error.

Thus this is the final update:

## Packages
    library(igraph)
    library(tidygraph)
    library(ggraph)
    library(ggplot2)
    library(tidyverse)

    ## Edge and node
    edge <- data.frame(from=c(0,0,0,0,1,2,3),
                       to=c(0,1,2,3,0,0,0),
                       weight=c(1,3,1,1,3,1,1))
    node <- data.frame(id=c(0,1,2,3),
                       p=c(9,1,0,0),
                       w=c(0,2,0,0),
                       s=c(0,1,1,1),
                       size=c(9,3,1,1),
                       gr=c(0,1,1,2))

    ## Load data frames as tbl_graph class
    edge <- edge %>% mutate(from=from+1,to=to+1)
    # THIS IS QUITE STRANGE OPERATION FOR CHANGING COLOR
    node <- node %>% mutate_at(vars(p,w,s,size),funs(ifelse(.==0,NA,.)))
    net <- tbl_graph(nodes=node,edges=edge,directed=TRUE)

## Set arrows
ar <- arrow(angle=30,length=unit(5,"mm"),ends="last",type="closed")
## Plot
ggraph(net,layout="graphopt") +
    ## Edges
    geom_edge_link(aes(start_cap=circle(log(node1.size)+2,unit="native"),
                       end_cap=circle(log(node2.size)+2,unit="native"),
                       width=weight,label=weight),
        position="identity",angle_calc="along",force_flip=TRUE,
        label_dodge=unit(4.0,"mm"),label_push=unit(-0.4,"mm")) +
        ## Width scale
        scale_edge_width(range=c(0.4,4),breaks=c(1:10),name="Movements\nbetween zones") +
    ## Add arrows separately
    geom_edge_link(arrow=ar,aes(start_cap=circle(log(node1.size)+1,unit="native"),
        end_cap=circle(log(node2.size)+1,unit="native"))) +
    ## Nodes
        ## Plot location id
        geom_node_label(aes(label=id,hjust=log(size+6),vjust=log(size+6)),repel=TRUE,
                        label.padding=unit(0.8,"mm"),label.r=unit(0.0,"mm"),label.size=0.1,size=3.5) +
        ## Circle
        geom_node_circle(aes(r=log(size)+1),color="black",fill="white",size=0.4) +
        ## Plot work activity: NOT KNOW WHY IT WORKS!!
        geom_node_text(aes(size=ifelse(is.na(w),0,w),hjust=log(w)+0.4,color=ifelse(w==0,"white","red")),label="w",
                       position="identity",vjust=0.4,fontface="bold") +
        ## Plot school activity
        geom_node_text(aes(size=ifelse(is.na(s),0,s),hjust=-log(s)-0.2,color=ifelse(s==0,"white","blue")),label="s",
                       position="identity",vjust=0.4,fontface="bold") +
        ## Edit legend
        scale_size_continuous(range=c(0,5),breaks=c(1:100),name="Numberof\nActivities",
                   guide=guide_legend(override.aes=list(label="a",color="black"))) +
        scale_color_manual(name="Type of Activity",guide=guide_legend(override.aes=list(label=c("w","s"))),
                           values=c("red","blue"),labels=c("Work","School")) +
    ## Theme
    theme_graph() + coord_fixed()

enter image description here

However, as it is still ugly codes, I am still waiting for your suggestions for more appropriate operations.

Doable answered 29/7, 2018 at 14:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.