Heat map- adjusting color range - r

library(gplots)
shades= c(seq(-1,0.8,length=64),seq(0.8,1.2,length=64),seq(1.2,3,length=64))
heatmap.2(cor_mat, dendrogram='none', Rowv=FALSE, Colv=FALSE, col=redblue(64),
breaks=shades, key=TRUE, cexCol=0.7, cexRow=1, keysize=1)
There is some problem with breaks. Wish to receive help on it.
After running the code I get this error message
Error in image.default(1:nc, 1:nr, x, xlim = 0.5 + c(0, nc), ylim = 0.5 + : must have one more break than colour
Thank you for your time and consideration.

Well, we don't have cor_mat so we can't try this ourselves, but the problem seems to be what it says on the tin, isn't it? The way heatmap (and generally all functions based on image) works with breaks and a vector of colours, is that the breaks define the points where changes in the value of your data matrix means the colour changes. In short, if break = c(1,2,3), and your col = c("red", "blue"):
values < 1 will be transparent
values >= 1, <= 2 will be plotted as red
values > 2, <= 3 will be plotted as blue
values > 3 will be transparent
What's going on in your code is that with 'shade' you've supplied a length 3*64 vector to break, while redblue(64) only gives you 64 colours. Try replacing redblue(64) with, say, redblue(3*64-1).

Related

R corrplot - color relying on value

I have a binary data.frame (53115 rows; 520 columns) and I want to plot a correlation plot. I want to colour it based on the values, correlation values >=0.95 (red), otherwise, blue.
correl <- abs(round(cor(bin_mat), 2))
pdf("corrplot.pdf", width = 200, height = 200)
a <- corrplot(correl, order = "hclust", addCoef.col = "black", number.cex=0.8, cl.lim = c(0,1), col=c(rep("deepskyblue",19) ,"red"))
dev.off()
I get the correlation plot but in many cases I get a wrong coloring (see below on 0.91).
data: file
How can I manage to have a right coloring?
In general corrplot library is quite weird when it comes to cl.lim and colors. For some reason it doesn't seem to matter if you set cl.lim or not - the colors will still be distributed from -1 to 1.
So in your case just use 39 blue colors instead of 19 (to cover the range from -1 to 1):
cors <- cor(iris[,-5])
cors[cbind(c(1,2), c(2,1))] <- 0.912
corrplot(cors, col=c(rep("blue", 39), "red"), cl.lim=c(-1,1), addCoef.col="black")
And the result:

Plotting a chessboard with no external libraries

I'd like if someone could help me with this problem I've been hours trying to solve.
I have to plot a chessboard with no external libraries (using only the default graphical functions in R).
My attempt is working with black squares till I have to filter and paint the white squares:
plot(c(1:9),c(1:9),type="n")
for (i in 1:8){
rect(i,1:9,i+1,9,col="black",border="white")
}
I could do it manually in this way, but I know there's a simpler way:
plot(c(1:9),c(1:9),type="n")
rect(1, 2, 2, 1,col="black",border="white")
rect(4, 1, 3, 2,col="black",border="white")
rect(6, 1, 5, 2,col="black",border="white")
rect(7, 1, 8, 2,col="black",border="white")
(...)
I've tried adding a function to filter even numbers inside the loop but doesn't seems to works for me.
I would appreciate any suggestion!
Use image and just repeat 0:1 over and over. Then you can mess with the limits a bit to make it fit nice.
image(matrix(1:0, 9, 9), col=0:1, xlim=c(-.05,.93), ylim=c(-.05,.93))
Just change the col= argument in your solution as shown. Also note that c(1:9) can be written as just 1:9 :
plot(1:9, 1:9, type = "n")
for (i in 1:8) {
col <- if (i %% 2) c("white", "black") else c("black", "white")
rect(i, 1:9, i+1, 9, col = col, border = "white")
}
remembering Jeremy Kun's post
https://jeremykun.com/2018/03/25/a-parlor-trick-for-set/ on Set helped
me figure the hard part (for me) of this question. i realized that
diagonals on the board (what bishops move on) have a constant color.
and, so, their Y-intercept (where they hit the Y-axis) will uniquely
determine their color, and adjacent Y values will have different
colors. for a square at (x,y), the y intercept (since the slope is 1)
will be at Y == (y-x). since the parity is the same for addition as
for subtraction, and i'm never sure which mod functions (in which
languages) may give a negative result, i use "(x+y) %% 2".
b <- matrix(nrow=8,ncol=8) # basic board
colorindex <- (col(b)+row(b))%%2 # parity of the Y-intercept
# for each square
colors <- c("red", "white")[colorindex+1] # choose colors
side <- 1/8 # side of one square
ux <- col(b)*side # upper x values
lx <- ux-side # lower x values
uy <- row(b)*side # upper y
ly <- uy-side # upper y
plot.new() # initialize R graphics
rect(lx, ly, ux, uy, col=colors, asp=1) # draw the board

colorRamp returns 0

I'm trying to plot lines and color the lines based on the probability of that connection. Given a vector of probabilities, I use:
colfunc <- colorRamp(c("white", "red"))
colors <- colfunc(probs)
colors is then an nx3 matrix of rgb values. However, colfunc quite often returns a 0 value, so when i attempt to plot using these colors, R complains
Error in col2rgb(colors) : numerical color values must be positive
Is there an error in the way I am defining my color function?
Your function works fine, I think, but it doesn't return colors you can use with plot, because plot wants a color, not RGB values in a matrix.
There's probably a better way, but you can simply covert the matrix:
probs <- runif(10)
colors <- colfunc(probs)
my_col = apply(colors, MARGIN = 1, function(x) rgb(x[1]/255, x[2]/255, x[3]/255))
plot(1:10, 1:10, col = my_col) # should work fine
or you could just wrap your function
better_colfunc <- function(x, ramp = colorRamp(c("white", "red"))) {
colors <- ramp(x)
colors = apply(colors, MARGIN = 1, function(x) rgb(x[1]/255, x[2]/255, x[3]/255))
return(colors)
}
plot(1:10, 1:10, col = better_colfunc(probs, ramp = colfunc))
As for "colfunc quite often returns a 0 value", and other issues, you'll need to share both some data (what do your probs look like?) as well as perhaps the actual plotting code. See here for tips on making reproducible questions.
I am a bit confused what you are trying to do...the col2rgb function returns rgb values, so if you already have those then what do you want?
Or if you want rgb, why not use:
col2rgb(c("white", "red"))

Problems with pheatmap usage

I'm trying to play around with pheatmap and getting stuck at the very beginning.
Creating a toy example:
library(pheatmap)
set.seed(1)
my.mat <- matrix(rnorm(90), nrow = 30, ncol = 30)
rownames(my.mat) <- 1:30
colnames(my.mat) <- 1:30
col.scale = colorRampPalette(c("red", "blue"), space = "rgb")(10)
breaks.size = 11
pheatmap(my.mat, color = col.scale, breaks = breaks.size, border_color = NA, cellwidth = 10, cellheight = 10)
Throws this error message:
Error in unit(y, default.units) : 'x' and 'units' must have length > 0
And the plot it produces doesn't seem right:
For example, I can't understand why the top right cells are white. i also thought the setting cellwidth = 10 and cellheight = 10 means getting square cells and not rectangular. And finally, if anyone knows if it's possible to have the row names and col names apear on the same side of the heat map as the dendograms (i.e., at the tips of the dendogram), that'll be great.
Well, the reason you are getting that error is that you are using the breaks= parameter incorrectly. From the ?pheatmap help page
breaks: a sequence of numbers that covers the range of values in mat and is one element longer than color vector. Used for mapping values to colors. Useful, if needed to map certain values to certain colors, to certain values. If value is NA then the breaks are calculated automatically.
You can't just pass a single value like you might with other functions.
Also i'm not sure what you are saying about the cells not being square. You are plotting a 30x30 square shape (at least it is for me). Because you are clustering, you're only getting one color per cluster.
I'm guessing part of the problem may be you're only generating 90 random variables for a 900 cell matrix so those values are repeating (your data is very structured). Perhaps you meant
my.mat <- matrix(rnorm(900), nrow = 30, ncol = 30)
doing so gives you the following plot

R axis text no dots

I want to add the following x-axis label to my bar plot but unfortunately R does not recognize the character '!' and prints dots instead of whitespaces:
I want: I get:
!src x.x.x.x X.src.x.x.x.x
!TCP X.TCP
!udp && !src x.x.x.x X.udp.....src.x.x.x.x
Additionally a would like to increase the margin because the text is to long and when setting the size over 'cex.names=0.6' then it just vanishes!?
There are two reason I can think of that R will have substituted X. for instances of !.
I suspect that the labelling you are seeing is due to R's reading of your data. Those column names aren't really syntactically valid and the erroneous character has been replaced by X.. This happens at the data import stage, so I presume you didn't check how R had read your data in?, or
You have a vector and the names of that vector are similarly invalid and R has done the conversion.
However, as you haven't made this reproducible it could be anything.
To deal with case 1 above, either edit your data file to contain valid names or pass check.names = FALSE in your read.table() call used to read in the data. Although doing the latter will make it difficult for you to select variable by name without quoting the name fully.
If you have a vector, then you can reset the names again:
> vec <- 1:5
> names(vec) <- paste0("!",LETTERS[1:5])
> vec
!A !B !C !D !E
1 2 3 4 5
> barplot(vec)
Also note that barplot() has a names.arg argument that you can use to pass it the labels to draw beneath each bar. For example:
> barplot(vec, names.arg = paste0("!", letters[1:5]))
which means you don't need to rely on what R has read in/converted for you as you tell it exactly what to label the plot with.
To increase the size of the margin, there are several ways to specify the size but I find setting it in terms of number of lines most useful. You change this via graphical parameter mar, which has the defaults c(5,4,4,2) + 0.1 which correspond to the bottom, left, top, and right margins respectively. Use par() to change the defaults, for example in the code below the defaults are store in op and a much larger bottom margin specified
op <- par(mar = c(10,4,4,2) + 0.1)
barplot(vec, names.arg = paste0("!", letters[1:5]), las = 2)
par(op) ## reset
The las = 2 will rotate the bar labels 90 degrees to be perpendicular to the axis.
One option is to use ann=F and add anotation to the plot using mtext.
x <- 1:2
y <- runif(2, 0, 100)
par(mar=c(4, 4, 2, 4))
plot(x, y, type="l", xlim=c(0.5, 2.5), ylim=c(-10, 110),
axes=TRUE, ann=FALSE)
Then add annotation:
mtext("!udp && !src x.x.x.x ", side=1, line=2)
Edit It is a question of a barplot and not simple plot.
as said in Gavin solution, the names argument can be setted. Here I show an example.
barplot(VADeaths[1:2,], angle = c(45, 135),
density = 20, col = "grey",
names=c("!src x.x.x.x", "!TCP", "!udp && !src x.x.x.x", "UF"),
horiz=FALSE)

Resources