4
votes

I'm trying to create a chart in R using ggplot and I need a legend to describe what the different text labels are. The dataset (pfdavar) is as follows:

pfdavar <- read.table(header=TRUE,row.names=1,text="
Scientific_Name X1  X2  Function    Labels  Species
Accipiter_gentilis1 -4.89789193 -4.647159032    Carnivore   1   Accipiter_gentilis
Accipiter_gentilis2 -4.85572869 -4.136258682    Carnivore   1   Accipiter_gentilis
Accipiter_gentilis3 -4.53679492 -1.800944748    Carnivore   1   Accipiter_gentilis
Accipiter_gentilis4 -6.09443847 -0.959612873    Carnivore   1   Accipiter_gentilis
Accipiter_gentilis5 -6.05461651 -4.960788555    Carnivore   1   Accipiter_gentilis
Acciptiter_nisus1   -3.41413514 -0.895822312    Carnivore   2   Accipiter_nisus
Acciptiter_nisus2   -3.19652756 -0.888246165    Carnivore   2   Accipiter_nisus
Acciptiter_nisus3   -3.12483784 -0.999500166    Carnivore   2   Accipiter_nisus
Acciptiter_nisus4   -2.66618148 -2.960531036    Carnivore   2   Accipiter_nisus
Acciptiter_nisus5   -3.54795755 -2.818834269    Carnivore   2   Accipiter_nisus
Acciptiter_nisus6   -3.25976501 -2.356532832    Carnivore   2   Accipiter_nisus
Acciptiter_nisus7   -3.37935944 -1.968577396    Carnivore   2   Accipiter_nisus
Acciptiter_nisus8   -3.0595512  -2.562750671    Carnivore   2   Accipiter_nisus
Acciptiter_nisus9   -3.27594514 -1.773717162    Carnivore   2   Accipiter_nisus
Acciptiter_nisus10  -3.28664004 -2.111224987    Carnivore   2   Accipiter_nisus
Aix_sponsa1 -1.4390108  1.536380546 Omnivore    3   Aix_sponsa
Aix_sponsa2 -2.17774592 1.419977832 Omnivore    3   Aix_sponsa
Aix_sponsa3 -0.73377916 1.652091362 Omnivore    3   Aix_sponsa
Aix_sponsa4 -0.68365602 1.748682677 Omnivore    3   Aix_sponsa
Aix_sponsa5 -1.02730778 1.868245903 Omnivore    3   Aix_sponsa
Aix_sponsa6 -1.37813364 1.974331359 Omnivore    3   Aix_sponsa
Aix_sponsa7 -0.74135489 1.427638468 Omnivore    3   Aix_sponsa
Aix_sponsa8 -0.58858907 1.004532252 Omnivore    3   Aix_sponsa
Aix_sponsa9 -1.1451094  1.769762482 Omnivore    3   Aix_sponsa
Aix_sponsa10    -1.28796936 1.929869081 Omnivore    3   Aix_sponsa
Anas_crecca1    -1.35096092 1.419587444 Omnivore    4   Anas_crecca
Anas_crecca2    -1.15412046 1.551324297 Omnivore    4   Anas_crecca
Anas_crecca3    -0.46402248 1.09274552  Omnivore    4   Anas_crecca
Anas_crecca4    -0.45462158 1.766419599 Omnivore    4   Anas_crecca
Anas_crecca5    0.13085385  1.373888208 Omnivore    4   Anas_crecca
Anas_crecca6    -0.25686211 2.229749359 Omnivore    4   Anas_crecca
Anas_crecca7    -0.9650909  1.296567761 Omnivore    4   Anas_crecca
Anas_crecca8    -1.26040491 1.981659794 Omnivore    4   Anas_crecca
Anas_crecca9    -1.03942764 1.489003168 Omnivore    4   Anas_crecca
Anas_crecca10   -0.97216996 1.336046865 Omnivore    4   Anas_crecca
Apus_apus1  1.88334138  -0.100251918    Insectivore 5   Apus_apus
Apus_apus2  0.75592041  -0.934233835    Insectivore 5   Apus_apus
Apus_apus3  0.71275049  -1.327860015    Insectivore 5   Apus_apus
Apus_apus4  1.1990241   0.399503737 Insectivore 5   Apus_apus
Apus_apus5  2.14285406  0.39050903  Insectivore 5   Apus_apus
Apus_apus6  2.26623205  1.082865398 Insectivore 5   Apus_apus
Apus_apus7  2.19534512  1.170083188 Insectivore 5   Apus_apus
Apus_apus8  1.82943832  0.353572547 Insectivore 5   Apus_apus
Apus_apus9  1.32492464  -0.005098561    Insectivore 5   Apus_apus
Apus_apus10 3.33227261  -0.172660264    Insectivore 5   Apus_apus
Branta_bernicla1    -2.59541115 0.403284268 Graminivore 6   Branta_bernicla
Branta_bernicla2    -2.29101252 0.518276194 Graminivore 6   Branta_bernicla
Branta_bernicla3    -3.75432432 1.051798493 Graminivore 6   Branta_bernicla
Branta_bernicla4    -2.46565059 0.450162234 Graminivore 6   Branta_bernicla
Branta_bernicla5    -2.27965667 -0.298584584    Graminivore 6   Branta_bernicla
Branta_bernicla6    -2.52807499 0.221669554 Graminivore 6   Branta_bernicla
Branta_bernicla7    -3.19899834 -0.439541025    Graminivore 6   Branta_bernicla
Branta_bernicla8    -2.9235117  0.835465853 Graminivore 6   Branta_bernicla
Branta_bernicla9    -2.1349146  -0.461085227    Graminivore 6   Branta_bernicla
Branta_bernicla10   -2.72727687 0.858812955 Graminivore 6   Branta_bernicla
Branta_canadensis1  -2.61921103 0.197699691 Graminivore 7   Branta_canadensis
Branta_canadensis2  -1.84266453 -1.407186966    Graminivore 7   Branta_canadensis
Branta_canadensis3  -2.29562301 -0.538735389    Graminivore 7   Branta_canadensis
Branta_canadensis4  -1.57554385 0.566449848 Graminivore 7   Branta_canadensis
Bucephala_islandica1    -2.81886145 2.917895842 Omnivore    8   Bucephala_islandica
Bucephala_islandica2    -2.04171303 2.417351605 Omnivore    8   Bucephala_islandica
Bucephala_islandica3    -3.63391644 2.565876003 Omnivore    8   Bucephala_islandica
Bucephala_islandica4    -2.76309326 2.485341013 Omnivore    8   Bucephala_islandica
Bucephala_islandica5    -2.9319585  3.029284674 Omnivore    8   Bucephala_islandica
Caprimulgus_climacurus1 2.97008877  -0.649580557    Insectivore 9   Caprimulgus_climacurus
Caprimulgus_climacurus2 4.39486789  -0.729532552    Insectivore 9   Caprimulgus_climacurus
Caprimulgus_climacurus3 4.5143613   -0.226964193    Insectivore 9   Caprimulgus_climacurus
Caprimulgus_europaeus1  5.44615841  -1.021666961    Insectivore 10  Caprimulgus_europaeus
Caprimulgus_europaeus2  5.02364267  -0.890099077    Insectivore 10  Caprimulgus_europaeus
Caprimulgus_europaeus3  5.21067804  -1.578068157    Insectivore 10  Caprimulgus_europaeus
Clanga_clanga1  -4.29958313 -4.522075437    Carnivore   11  Clanga_clanga
Clanga_clanga2  -5.39490832 -4.828912341    Carnivore   11  Clanga_clanga
Clanga_pomarina1    -4.38077048 -2.784564708    Carnivore   12  Clanga_pomarina
Clanga_pomarina2    -4.6561379  -4.252797443    Carnivore   12  Clanga_pomarina
Clanga_pomarina3    -5.48538959 -3.579093142    Carnivore   12  Clanga_pomarina
Delichon_urbicum1   2.2925  0.430657351 Insectivore 13  Delichon_urbicum
Delichon_urbicum2   1.54099519  1.459719746 Insectivore 13  Delichon_urbicum
Delichon_urbicum3   0.99773878  0.274581581 Insectivore 13  Delichon_urbicum
Delichon_urbicum4   1.24467923  1.236789373 Insectivore 13  Delichon_urbicum
Delichon_urbicum5   0.53504479  0.154682421 Insectivore 13  Delichon_urbicum
Delichon_urbicum6   1.53214527  0.91890228  Insectivore 13  Delichon_urbicum
Delichon_urbicum7   1.49818001  1.089675735 Insectivore 13  Delichon_urbicum
Delichon_urbicum8   0.67390299  0.753096969 Insectivore 13  Delichon_urbicum
Delichon_urbicum9   1.93683118  0.918165987 Insectivore 13  Delichon_urbicum
Delichon_urbicum10  1.58513146  1.564374345 Insectivore 13  Delichon_urbicum
Hirundo_rustica1    2.62925523  1.651726581 Insectivore 14  Hirundo_rustica
Hirundo_rustica2    2.14444347  2.273743756 Insectivore 14  Hirundo_rustica
Hirundo_rustica3    2.44316384  1.305086968 Insectivore 14  Hirundo_rustica
Hirundo_rustica4    3.15948914  1.458235727 Insectivore 14  Hirundo_rustica
Hirundo_rustica5    2.45355055  1.365638627 Insectivore 14  Hirundo_rustica
Hirundo_rustica6    3.06169729  1.275884535 Insectivore 14  Hirundo_rustica
Hirundo_rustica7    2.38793666  1.636555833 Insectivore 14  Hirundo_rustica
Hirundo_rustica8    2.66767101  0.645046239 Insectivore 14  Hirundo_rustica
Hirundo_rustica9    3.71351475  1.661709624 Insectivore 14  Hirundo_rustica
Hirundo_rustica10   2.93209807  0.734178456 Insectivore 14  Hirundo_rustica
Mergus_merganser1   0.29942933  -2.433390971    Piscivore   15  Mergus_merganser
Mergus_merganser2   0.98081612  -2.572393002    Piscivore   15  Mergus_merganser
Mergus_merganser3   0.72001717  -2.569943671    Piscivore   15  Mergus_merganser
Mergus_merganser4   0.46411239  -2.786791001    Piscivore   15  Mergus_merganser
Mergus_merganser5   -0.44219165 -1.601086246    Piscivore   15  Mergus_merganser
Mergus_merganser6   -0.46454582 -1.360541224    Piscivore   15  Mergus_merganser
Mergus_merganser7   -1.15574664 -2.601269214    Piscivore   15  Mergus_merganser
Mergus_merganser8   0.16982656  -2.97723875 Piscivore   15  Mergus_merganser
Spatula_clypeata1   6.07310551  -2.358533867    Filter-feeder   16  Spatula_clypeata
Spatula_clypeata2   7.22049562  -3.37755176 Filter-feeder   16  Spatula_clypeata
Spatula_clypeata3   6.50789136  -2.300145446    Filter-feeder   16  Spatula_clypeata
Spatula_clypeata4   5.47730013  -2.176186104    Filter-feeder   16  Spatula_clypeata
Spatula_clypeata5   5.53559984  -2.405227327    Filter-feeder   16  Spatula_clypeata
Spatula_clypeata6   7.97963585  -2.70056017 Filter-feeder   16  Spatula_clypeata
Spatula_clypeata7   6.71942913  -1.932583426    Filter-feeder   16  Spatula_clypeata
Spatula_clypeata8   5.81775012  -2.058246029    Filter-feeder   16  Spatula_clypeata
Spatula_clypeata9   7.20591453  -2.997222777    Filter-feeder   16  Spatula_clypeata
Spatula_clypeata10  8.01402202  -3.384188559    Filter-feeder   16  Spatula_clypeata
Tachymarptis_melba1 4.93212078  -0.758952678    Insectivore 17  Tachymarptis_melba
Tadorna_tadorna1    -1.03512249 4.286499709 Omnivore    18  Tadorna_tadorna
Tadorna_tadorna2    0.45753486  3.348021245 Omnivore    18  Tadorna_tadorna
Tadorna_tadorna3    0.08608732  4.270813056 Omnivore    18  Tadorna_tadorna
Tadorna_tadorna4    -1.43964831 3.38875373  Omnivore    18  Tadorna_tadorna
Tadorna_tadorna5    -0.96090197 4.416417469 Omnivore    18  Tadorna_tadorna
Tadorna_tadorna6    -0.40120783 3.807289885 Omnivore    18  Tadorna_tadorna
Tadorna_tadorna7    -0.90882097 4.452652604 Omnivore    18  Tadorna_tadorna
Tadorna_tadorna8    -0.4036924  4.103030427 Omnivore    18  Tadorna_tadorna
Tadorna_tadorna9    -0.46248229 4.198274967 Omnivore    18  Tadorna_tadorna
")

And the code that I'm using is as follows to get the image below:

library(ggplot2)
library(dplyr)
groups<-pfdavar$Function
labels<-pfdavar$Labels
species<-pfdavar$Species
find_hull <- function(df) df[chull(df$X1, df$X2), ]
hulls <- plyr::ddply(pfdavar, "groups", find_hull)
pfda_plot <- ggplot(data=pfdavar,aes(x=X1,y=X2,group=groups))+
  geom_point(aes(colour=groups))+
  geom_polygon(data=hulls,alpha=0.2,aes(fill=groups))+
  xlab("pFDA1")+
  ylab("pFDA2")+
  geom_text(aes(label=labels,fontface=1),hjust=0,vjust=0,size=3)+
  theme_classic()+
  theme(legend.title=element_blank())
pfda_plot

pFDA I don't know how to assign the "Species" column in my dataset to the "Labels" column so that ggplot creates a label describing which species each number represents. I'm sure it has something to do with creating a new aes() but so far I haven't had any success in getting it to work...

Any help would be appreciated!

Thanks,

Carolina

2
Images of tables are not helpful. People cannot enter them into their R session to try things in order to provide a solution that works. Please provide code that generates a small table with suitable features. Also, the built-in legend maps ggplot2 aesthetics to data variables. What you are asking for is a mapping of one data variable to another data variable. I don't think there is a simple way to create this. Consider instead mapping your Species to point shape (or colour or fill or size), instead of plotting custom text labels. Then you can get a built-in legend for the species.cymon
Welcome to Stack Overflow! Could you make your problem reproducible by sharing a sample of your data so others can help (please do not use str(), head() or screenshot)? You can use the reprex and datapasta packages to assist you with that. See also Help me Help you & How to make a great R reproducible example?Tung
Try geom_text(aes(label=Species),fontface=1,hjust=0,vjust=0,size=3)StupidWolf
Hi @cymon thanks for your reply. I've just tried your suggest about using different shapes and this would involve using 18 different shapes (or combinations of shape, size, etc) which makes for a very confusing and busy graph. I don't suppose you know of any way of creating a manual legend for my text labels then?Carolina Karoullas
Hi @Tung thanks for your reply. I've just edited my question. I hope that solves the problem? Maybe? I've copy and pasted the above code into R and it does seem to work.Carolina Karoullas

2 Answers

2
votes

Legends for geom_text can only be called via color and you have already used that in your geom_points().

To get the plot you like, and keep the current color scheme, let's try adding a new color scale, using ggnewscale and we still make all your text black (see scale_color_manual):

library(ggplot2)
library(grid)
library(ggnewscale)

pfda_plot <- ggplot(data=pfdavar,aes(x=X1,y=X2,group=groups))+
  geom_point(aes(colour=groups))+
  geom_polygon(data=hulls,alpha=0.2,aes(fill=groups))+
  xlab("pFDA1")+
  ylab("pFDA2")+
  theme_classic()+
  theme(legend.title=element_blank())+
  new_scale_color()+
  geom_text(aes(label=labels,col=Species),
  fontface=1,hjust=0,vjust=0,size=3)+
  scale_color_manual(values=rep("black",18))

enter image description here

The above gives you something close, just that it is all 'a' for geom_text legend. What we need to do now, is change the default 'a', and for this I used @MarcoSandri's solution to change the default "a" in legend for geom_text()

g <- ggplotGrob(pfda_plot)
lbls <- 1:18
idx <- which(sapply(g$grobs[[15]][[1]][[1]]$grobs,function(i){
  "label" %in% names(i)}))
for(i in 1:length(idx)){
g$grobs[[15]][[1]][[1]]$grobs[[idx[i]]]$label <- lbls[i]
}
grid.draw(g)

enter image description here

1
votes

You just need to create another group_label which is a combination of Labels and Species. Use factor() to rearrange the order if you want.

library(dplyr)
library(ggplot2)

find_hull <- function(df) { df[chull(df$X1, df$X2), ] }
hulls <- plyr::ddply(pfdavar, "Function", find_hull)
### or do it the dplyr/purrr way
# hulls <- pfdavar %>% 
#   group_by(Function) %>% 
#   group_modify(~ find_hull(.x)) %>% 
#   ungroup()
# hulls

pfdavar <- pfdavar %>% 
  mutate(group_label = paste0(Labels, " - ", Species))

pfda_plot <- ggplot(data = pfdavar, aes(x = X1, y = X2, group = group_label)) +
  geom_point(aes(colour = group_label)) +
  geom_polygon(data = hulls, alpha = 0.2, 
               aes(x = X1, y = X2, fill = Function), inherit.aes = FALSE) +
  xlab("pFDA1") +
  ylab("pFDA2") +
  geom_text(aes(label = Labels, fontface = 1), hjust = 0, vjust = 0, size = 3) +
  scale_fill_brewer(palette = 'Dark2') +
  theme_classic() +
  theme(legend.title = element_blank()) 
pfda_plot

pfdavar <- pfdavar %>% 
  ### or use Tjebo's comment
  # mutate(group_label2 = reorder(group_label, gtools::mixedorder(group_label)))
  mutate(group_label2 = factor(group_label, levels = unique(pfdavar$group_label[order(pfdavar$Labels)])))
pfdavar

pfda_plot2 <- ggplot(data = pfdavar, aes(x = X1, y = X2, group = group_label2)) +
  geom_point(aes(colour = group_label2)) +
  geom_polygon(data = hulls, alpha = 0.2, 
               aes(x = X1, y = X2, fill = Function), inherit.aes = FALSE) +
  xlab("pFDA1") +
  ylab("pFDA2") +
  geom_text(aes(label = Labels, fontface = 1), hjust = 0, vjust = 0, size = 3) +
  scale_fill_brewer(palette = 'Dark2') +
  theme_classic() +
  guides(col = guide_legend(ncol = 4, byrow = TRUE)) +
  theme(legend.title = element_blank()) +
  theme(legend.position = 'bottom')
pfda_plot2

Created on 2019-11-28 by the reprex package (v0.3.0)