1
votes

Below is a code that works using the plot() function to run a 2D scatterplot of Height vs Weight where points are classed as “Good”, “Fair”, “Poor” based on whether the Class value is 1, 2 or 3, respectively. Points for "Good" are bright green, "Fair", olive green and Poor, red. All points are the same size (pch=19). Is it possible to have different sizes and transparency for each data point depending on what each point is assigned in the “Group” column: either an Opaque and Small size point, Semi-transparent and Medium sized, or 100% Transparent and Large size point. Thanks for your ideas!

  df
  #           Group        Class      Height      Weight
  #  1       Opaque small     1 0.831777874 0.859223152
  #  2 Semi-transprnt med     2 0.751019511 0.807521752
  #  3 Semi-transprnt med     1 0.751019511 0.807521752
  #  4    Transprnt large     3 0.527390539 0.599957241
  #  5    Transprnt large     3 0.527390539 0.599957241

    color <- c(rgb(0, 1, 0, 1), rgb(0.5, 0.5, 0), rgb(1, 0, 0))
    plot(x=c(0.0, 0.5, 0.5, 0.0, 0.0), y=c(0.0, 0.0, 0.5, 0.5, 0.0), 
    type='l', col='gray', lwd=2,xlab='Height', ylab='Weight', 
    xlim=c(1,0), ylim=c(1, 0))
    par(new=T)
    plot(x=c(0.0, 0.5, 0.5, 0.0, 0.0), y=c(0.5, 0.5, 1, 1, 0.5), 
    type='l', col='gray', lwd=2, xlab='', ylab='', 
    xlim=c(1, 0.0), ylim=c(1, 0.0), axes=F)
    par(new=T)
    plot(x=c(0.5, 1, 1, 0.5, 0.5), y=c(0.0, 0.0, 0.5, 0.5, 0.0), 
    type='l', col='gray', lwd=2,
    xlab='', ylab='', xlim=c(1, 0.0), ylim=c(1, 0.0), axes=F)
    par(new=T)
    plot(x=c(0.5, 1, 1, 0.5, 0.5), y=c(0.5, 0.5, 1, 1, 0.5), type='l', 
    col='gray', lwd=2, xlab='', ylab='', 
    xlim=c(1, 0.0), ylim=c(1, 0.0), axes=F)
    par(new=T)
    for (i in 1:3) {
    plot(Height[Class==i], Weight[Class==i], xlim=c(0, 1), ylim=c(0, 1), 
    col=color[i], pch=19, xlab='', ylab='', axes=F)
    par(new=T)
    }
    legend(0.8, 0.586,legend=c('Good', 'Fair', 'Poor'), pch=19, 
    col=color, title='Class')
1
hey, you might take a look at this and this - mischva11
The Group and Class columns in the example df aren't consistent. Which one is correct? Also, should the plot function have Weight instead of Length? - A. S. K.
Weight is on the x axis and Length is y axis on scatterplot. What do you mean by plot function have Weight instead of Length?Group and Class columns in the example df aren't consistent? In the above code, I have plotted values in the "Class" column. I could enter a column for size and a separate column for transparency if that makes it easier? - AlexP
From your question, it sounds like the Class of each row should uniquely determine its Group (1 -> Opaque small, etc.). But lines 1 and 3 in the example have the same Class but different Groups, and lines 2 and 3 have the same Group but different Classes. Also, the last call to plot has Length[class==i] as its second argument, but there's no Length column in df. - A. S. K.
Apologies, I have edited Length to Weight. Class and Group are not related Class is a biological condition. Group is based on the number of replicates for a particular site. If I plot all 900 points (some of which are replicates) the data points can overlap and obscure points underneath. To get round this, I wanted to plot an opaque small point that would represent 1 rep, semi-transparent medium sized point for 2-4 reps and transparent large point for reps > 5. I have classified those replicate groupings which are shown under column Group. Any ideas how to approach this? Thanks. - AlexP

1 Answers

0
votes

Here's an approach that adds transparency using the method described in this answer (as suggested by @mischva11). First, add columns that contain the desired plotting properties:

library(dplyr)
library(tidyr)
library(scales)
df = df %>%
  separate(Group, into = c("Transparency", "Size"), sep = " ") %>%
  mutate(Color = case_when(Class == 1 ~ "Chartreuse",
                           Class == 2 ~ "Olive Drab",
                           Class == 3 ~ "Red"),
         Alpha = case_when(Transparency == "Opaque" ~ 0.9,
                           Transparency == "Semi-transprnt" ~ 0.9,
                           Transparency == "Transprnt" ~ 0.3),
         Size = case_when(Size == "small" ~ 0.8,
                          Size == "med" ~ 1,
                          Size == "large" ~ 1.2))

The replace the for loop in the original code with the following:

plot(df$Height, df$Weight, xlim = c(0, 1), ylim = c(0, 1),
     col = df$Color, pch = 21, xlab = "", ylab = "", axes = F,
     cex = df$Size, bg = alpha(df$Color, df$Alpha))

Edit: Using pch = 21 allows us to control the fill and border of the point separately (col for the border, bg for the fill). This example applied transparency to the fill but not the border.

On my machine, the semi-transparent point doesn't actually appear to be very transparent at all, so this might not quite accomplish what you're looking for. You could play around with the alpha values, or you could try ggplot instead. Here's how:

library(dplyr)
library(tidyr)
library(ggplot2)
df = df %>%
  separate(Group, into = c("Transparency", "Size"), sep = " ") %>%
  mutate(Color = case_when(Class == 1 ~ rgb(0, 1, 0),
                           Class == 2 ~ rgb(0.5, 0.5, 0),
                           Class == 3 ~ rgb(1, 0, 0)),
         Alpha = case_when(Transparency == "Opaque" ~ 1,
                           Transparency == "Semi-transprnt" ~ 0.4,
                           Transparency == "Transprnt" ~ 0.2),
         Size = case_when(Size == "small" ~ 1,
                          Size == "med" ~ 2,
                          Size == "large" ~ 4))
ggplot(df, aes(x = Height, y = Weight, col = Color, alpha = Alpha, size = Size)) +
  geom_point() +
  scale_color_identity() +
  scale_alpha_identity()

This is maybe a little better, although to me, as a naive viewer, it's difficult to distinguish between ordinary points (with expected colors) and overlapping points (with colors that are the sum of other colors). But this may be easier to see with the full dataset. Again, you could try playing around with the specific sizes and alpha values to see what works.