Is there a way to produce a scatterplot using ggplot2 from a tibble with all the values in a single columns without pivot_wider?

Viewed 203

I have a dataframe with three columns:

sampleData <- structure(list(sgRNA = c("SFPQ_9", "SFPQ_9", "FBXO18_13", "FBXO18_13", 
                         "DDX21_55", "DDX21_55", "TAF6L_11", "TAF6L_11", "NAA40_3", "NAA40_3", 
                         "KDM5A_1", "KDM5A_1", "DGKH_17", "DGKH_17", "NAA30_15", "NAA30_15", 
                         "HMG20A_8", "HMG20A_8", "CASKIN1_35", "CASKIN1_35", "NUBP1_20", 
                         "NUBP1_20", "CTCF_9", "CTCF_9", "THAP11_17", "THAP11_17", "EZH1_9", 
                         "EZH1_9", "SMARCD2_21", "SMARCD2_21", "E2F6_6", "E2F6_6", "CENPA_11", 
                         "CENPA_11", "SP140_35", "SP140_35", "SETD4_3", "SETD4_3", "STAG3_9", 
                         "STAG3_9", "RAD54B_39", "RAD54B_39", "SMC1A_59", "SMC1A_59", 
                         "ZNF257_1246", "ZNF257_1246", "DYNC1I2_4", "DYNC1I2_4", "NTC_77", 
                         "NTC_77"), replicate = c("R1", "R2", "R1", "R2", "R1", "R2", 
                                                  "R1", "R2", "R1", "R2", "R1", "R2", "R1", "R2", "R1", "R2", "R1", 
                                                  "R2", "R1", "R2", "R1", "R2", "R1", "R2", "R1", "R2", "R1", "R2", 
                                                  "R1", "R2", "R1", "R2", "R1", "R2", "R1", "R2", "R1", "R2", "R1", 
                                                  "R2", "R1", "R2", "R1", "R2", "R1", "R2", "R1", "R2", "R1", "R2"
                         ), abundance = c(450L, 583L, 209L, 231L, 212L, 288L, 958L, 1103L, 
                                          562L, 717L, 388L, 452L, 290L, 330L, 201L, 281L, 142L, 258L, 608L, 
                                          850L, 218L, 328L, 522L, 711L, 623L, 772L, 371L, 471L, 56L, 52L, 
                                          160L, 135L, 359L, 416L, 213L, 348L, 301L, 416L, 185L, 256L, 222L, 
                                          238L, 347L, 536L, 765L, 973L, 115L, 117L, 102L, 132L)), row.names = c(NA, 
                                                                                                                -50L), class = c("tbl_df", "tbl", "data.frame"))

I would like to build a scatterplot. All the values are in the "abundance" column and the "replicate" specifies whether the observation is to be used as a coordinate along x or y axis. While "sgRNA" specifies the point. I understand I can pivot the data to wider format to generate two new columns "R1" and "R2" and plot them against each other using ggplot2, but is there a way to do this without pivoting?

4 Answers

I agree with @www's comment. It's not clear why you don't want to pivot.

In response to your question: No, you will need to reshape the data in one way or another.

If you don't like pivot_wider you could use xtabs with as.data.frame.matrix in the following way:

ggplot(as.data.frame.matrix(xtabs(abundance ~ ., data = sampleData)), aes(R1, R2)) + 
    geom_point()

enter image description here

But this is still a reshape from long to wide.

Sometimes I don't think it's about writing extra code, but more about reproducibility and understanding what was done, for yourself some time the road, or for someone else trying to understand what you did.

This below works, but hey not the most intuitive:

ggplot(data.frame(split(sampleData$abundance,sampleData$replicate)),
aes(x=R1,y=R2)) + geom_point()

enter image description here

I guess in some rare cases, such as you are using a company's computer, which you cannot have access to tidyr, then the following may work, which only uses dplyr and ggplot2.

library(dplyr)
library(ggplot2)

R1 <- sampleData %>% filter(replicate %in% "R1") %>% select(-replicate) 
R2 <- sampleData %>% filter(replicate %in% "R2") %>% select(-replicate)
R1R2 <- R1 %>% left_join(R2, by = "sgRNA", suffix = c("_R1", "_R2"))

ggplot(R1R2, aes(x = abundance_R1, y = abundance_R2)) +
  geom_point()

enter image description here

These do not use tidyr but do convert the data to wide form using other methods:

1) Read sampleData into a zoo object splitting on the second column, convert that to a data frame (which will have columns R1 and R2) and use qplot from ggplot2:

library(ggplot2)
library(magrittr)
library(zoo)

sampleData %>%
  read.zoo(split = 2, FUN = c) %>%
  as.data.frame %$%
  qplot(R1, R2)

screenshot

2) Another approach giving the same result is to use tapply:

library(ggplot2)
library(magrittr)

sampleData %$%
  tapply(.[[3]], .[-3], c) %>%
  as.data.frame.matrix %$% 
  qplot(R1, R2)

This could also be written without magrittr like this:

library(ggplot2)

with(as.data.frame.matrix(tapply(sampleData[[3]], sampleData[-3], c)),
  qplot(R1, R2))
Related