How to rotate the plot in r base package graphics? - r

I know this is a little bit too much, but I am plotting a dendrogram plot in r, and here is my code:
dd <- dist(scale(full[,c(1,2,3,4)]),method="euclidean")
hc = hclust(dd,method="ward.D2")
dend <- color_branches(as.dendrogram(hc),6)
labels_colors(dend) <-
rainbow_hcl(6)[sort_levels_values(
as.numeric(classified[, 9])[order.dendrogram(dend)]
)]
plot(dend,horiz=T)
and I got this plot:
Is there any way can do mirror symmetry to make it like this:(please ignore the difference in colour)

plot_horiz.dendrogram(dend, side = TRUE)
should do the trick. See https://rdrr.io/cran/dendextend/f/vignettes/FAQ.Rmd

Related

Is there a way to create a kissing people curve using ggplot2 in R

Is it possible to create custom graphs using ggplot2, for example I want to create a graph of kissing people.
Simple variant
Not completely, but partially, I was able to reproduce it, everything except for the "lines of the eyes" is not clear how to mark them
But how to make a more complex graph of kissing people. In general, is it possible to somehow approximate such a curve, more voluminou?
thank you for your help.
perhaps not what you are looking for, but if you have already got the image, and want to reproduce it in ggplot, then you can use the following method:
library(tidyverse)
library(magick)
library(terra)
# read image
im <- image_read("./data/kiss_1.png")
# conver to black/white image
im2 <- im %>%
image_quantize(
max = 2,
colorspace = "gray" )
# get a matrix of the pixel-colors
m <- as.raster(im2) %>% as.matrix()
# extract coordinates of the black pixels
df <- as.data.frame(which(m == "#000000ff", arr.ind=TRUE))
df$row <- df$row * -1
# plot point
ggplot(df, aes(x = col, y = row)) + geom_point()

Labelling circular dendextend dendrogram

I'm trying to plot a circular dendrogram of compositional data. Using the following code:
library(dendextend)
library(circlize)
library(compositions)
data("Hydrochem")
hydro<-Hydrochem
d <- dist(hydro[7:19], method="euclidean")
hc <- hclust(d, method = "average")
dend <- as.dendrogram(hc)
hydro$River <- as.character(hydro$River)
labels(dend) <- hydro$River[order.dendrogram(dend)]
plot(dend)
I can get a normal dendrogram of what I want with the correct label orders.
But when I run circlize_dendrogram(dend), I get this:
What's vexing me is the dendrogram in the middle - when I don't use the order of the dendrogram for the labels (i.e. just typing labels(dend) <- hydro$River), the inner dendrogram is fine and everything looks great.
I've tried altering the labels_track_height and dend_track_height settings to no avail, and when I run the same process on smaller toy datasets this issue doesn't arise.
Any ideas?
So you actually have two problems surfacing in your code:
1. The labels are not unique.
2. The plot does not give enough room for the labels, after you've updated them in the dendrogram object
The first problem can be solved by adding numbers to the non-unique labels you supply, thus making them unique. The solution for the second problem is to play with the labels_track_height argument in the circlize_dendrogram function. Here is the updated code (notice the last line, where the difference is):
library(dendextend)
library(circlize)
library(compositions)
data("Hydrochem")
hydro<-Hydrochem
d <- dist(hydro[7:19], method="euclidean")
hc <- hclust(d, method = "average")
dend <- as.dendrogram(hc)
tmp <- as.character(hydro$River)[order.dendrogram(dend)]
labels(dend) <- paste0(seq_along(tmp), "_", tmp)
plot(dend)
circlize_dendrogram(dend, labels_track_height = 0.4)
The output you get is this:
(This is now done automatically in dendextend 1.6.0, currently available on github - and later on also on CRAN)
So, the solution to this problem (if anyone can provide more details please do, because I don't really understand why this matters at all) is to add a second dend <- as.dendrogram(hc) call after defining the labels. So, the code looks like this:
d <- dist(hydro[7:19], method="euclidean")
hc <- hclust(d, method = "average")
dend <- as.dendrogram(hc)
hydro$River <- as.character(hydro$River)
labels(dend) <- hydro$River[order.dendrogram(dend)]
dend <- as.dendrogram(hc)
circlize_dendrogram(dend)
NOTE by another user: this does not solve the question.

How to cut a dendrogram in r

Okay so I'm sure this has been asked before but I can't find a nice answer anywhere after many hours of searching.
I have some data, I run a classification then I make a dendrogram.
The problem has to do with aesthetics, specifically; (1) how to cut according to the number of groups (in this example I want 3), (2) make the group labels aligned with the branches of the trees, (2) Re-scale so that there aren't any huge gaps between the groups
More on (3). I have dataset which is very species rich and there would be ~1000 groups without cutting. If I cut at say 3, the tree has some branches on the right and one 'miles' off to the right which I would want to re-scale so that its closer. All of this is possible via external programs but I want to do it all in r!
Bonus points if you can put an average silhouette width plot nested into the top right of this plot
Here is example using iris data
library(ggplot2)
data(iris)
df = data.frame(iris)
df$Species = NULL
ED10 = vegdist(df,method="euclidean")
EucWard_10 = hclust(ED10,method="ward.D2")
hcd_ward10 = as.dendrogram(EucWard_10)
plot(hcd_ward10)
plot(cut(hcd_ward10, h = 10)$upper, main = "Upper tree of cut at h=75")
I suspect what you would want to look at is the dendextend R package (it also has a paper in bioinformatics).
I am not fully sure about your question on (3), since I am not sure I understand what rescaling means. What I can tell you is that you can do quite a lot of dendextend. Here is a quick example for coloring the branches and labels for 3 groups.
library(ggplot2)
library(vegan)
data(iris)
df = data.frame(iris)
df$Species = NULL
library(vegan)
ED10 = vegdist(df,method="euclidean")
EucWard_10 = hclust(ED10,method="ward.D2")
hcd_ward10 = as.dendrogram(EucWard_10)
plot(hcd_ward10)
install.packages("dendextend")
library(dendextend)
dend <- hcd_ward10
dend <- color_branches(dend, k = 3)
dend <- color_labels(dend, k = 3)
plot(dend)
You can also get an interactive dendrogram by using plotly (ggplot method is available through dendextend):
library(plotly)
library(ggplot2)
p <- ggplot(dend)
ggplotly(p)

Dendrogram with Corrplot (R)

Does anyone have a method to adorn an R corrplot correlation plot with a dendrogram?
heatmaply actually has this functionality baked in since about December 2017! See the example below taken from the upcoming v1.0 vignette:
library("heatmaply")
r <- cor(mtcars)
## We use rcorr to calculate a matrix of p-values from correlation tests
library("Hmisc")
mtcars.rcorr <- rcorr(as.matrix(mtcars))
p <- mtcars.rcorr$P
heatmaply_cor(
r,
node_type = "scatter",
point_size_mat = -log10(p),
point_size_name = "-log10(p-value)",
label_names = c("x", "y", "Correlation")
)
The closest solution I know of is to use a heatmap on a correlation matrix, for example you could also use gplots::heatmap.2.
Here is how to do it using the heatmaply R package, which also offers an interactive interface where you can zoom-in and get a tooltip when hovering over the cells:
# for the first time:
# install.packages("heatmaply")
library(heatmaply)
my_cor <- cor(mtcars)
heatmaply_cor(my_cor)
Here is how it looks:
You can learn more about heatmaply in this vignette.

plot raster with discrete colors using rasterVis

I have a few rasters I would like to plot using gplot in the rasterVis package. I just discovered gplot (which is fantastic and so much faster than doing data.frame(rasterToPoints(r))). However, I can't get a discrete image to show. Normally if r is a raster, I'd do:
rdf=data.frame(rasterToPoints(r))
rdf$cuts=cut(rdf$value,breaks=seq(0,max(rdf$value),length.out=5))
ggplot(rdf)+geom_raster(aes(x,y,fill=cuts))
But is there a way to avoid the call to rasterToPoints? It is very slow with large rasters. I did find I could do:
cuts=cut_interval(r#data#values,n=5)
but if you set the fill to cuts it plots the integer representation of the factors.
Here is some reproducible data:
x=seq(-107,-106,.1)
y=seq(33,34,.1)
coords=expand.grid(x,y)
rdf=data.frame(coords,depth=runif(nrow(coords),0,2)))
names(rdf)=c('x','y','value')
r=rasterFromXYZ(rdf)
Thanks
gplot is a very simple wrapper around ggplot so don't expect too
much from it. Instead, you can use part of its code to build your own
solution. The main point here is to use sampleRegular to reduce the
number of points to be displayed.
library(raster)
library(ggplot2)
x <- sampleRegular(r, size=5000, asRaster = TRUE)
dat <- as.data.frame(r, xy=TRUE)
dat$cuts <- cut(dat$value,
breaks=seq(0, max(dat$value), length.out=5))
ggplot(aes(x = x, y = y), data = dat) +
geom_raster(aes(x, y, fill=cuts))
However, if you are open to plot without ggplot2 you may find useful
this other
answer.

Resources