Gradient in two directions in R - r

I need a gradient function for two "sides", let me explain:
Example:
x <- c(1,4,3,4,5,6,1,8,9,3)
then I need a array of color, the number 5 is the main color blue and the smaller and larger numbers are the gradient to red.
I found this
colorRampPalette(c("red", "blue"))
but if I do:
colfunc <- colorRampPalette(c("red", "blue"))
colfunc(10)
Returns a color progression from red to blue ignoring the value...
How can I do this?
Ps: I don't use any library...

For share with the community,
using the function "colorRampPalette", like:
col <- colorRampPalette(c('red', 'blue','red'))(10)[y]
where 10 is the range 1:10 with extremities red and in middle (5) in blue and other values are the gradient going to red.
in an example,
size <- 30 #number of value in the data vector
x <- c(1:size)
y <- c(1 ,2 ,3.5,3 ,4,
5 ,5.5,6 ,6.3,7,
5 ,2 ,1 ,0.5,1.6,
2.3,5.7,6 ,7 ,7.5,
8 ,9 ,11 ,12 ,10,
7 ,6.4,5 ,4.6 ,4)
col <- colorRampPalette(c('red', 'blue','red'))(12)[y]
plot(x, y) # draw the points, in black
for (i in 1:size-1) # draw the segments in colour
lines(x[i:(i+1)], y[i:(i+1)], type='o', pch=16, col=col[i])

Related

Color the edges of a graph in igraph

I would appreciate a piece of advice please : I am aiming to color the edges in a graph, by using IGRAPH package.
It works well for the big graph, however, when I decompose the graph into 2 subgraphs and color code those, the color of the edges change (unexpectedly).
more precisely, as an example -- we have a dataframe :
el <- data.frame(Partner1=c(1, 3, 4, 5, 6), Partner2=c(2, 2, 5, 7, 7), TYPE=c("DEL", "DEL", "DUP", "TRA", "TRA"))
el$COLOR[el$TYPE=="DEL"] <- "red"
el$COLOR[el$TYPE=="DUP"] <- "green"
el$COLOR[el$TYPE=="INS"] <- "yellow"
el$COLOR[el$TYPE=="INV"] <- "brown"
el$COLOR[el$TYPE=="TRA"] <- "blue"
g <- graph_from_data_frame(d = el, directed = TRUE)
plot(g, edge.color=el$COLOR)
And here decomposing the graph into 2 SUBGRAPHS :
g_decompose <- decompose.graph(g)
plot(g_decompose[[1]], edge.color=el$COLOR) ## here the edges are red (that is fine)
plot(g_decompose[[2]], edge.color=el$COLOR) ## here the edges shall be blue and green, not red and green
I solved it by using the R code :
plot(g_decompose[[1]], edge.color=edge_attr(g_decompose[[1]])$COLOR)
plot(g_decompose[[2]], edge.color=edge_attr(g_decompose[[2]])$COLOR)

Use customized order of axis with heatmap.2 function from gplots

I need to plot a heatmap using axis ordered as is in table.
My data is is csv format:
"X" "Mescla" "HCL" "HSL" "Kmeans" "soma"
"1" "DR" 15.33559 14.7499 14.7556 14.32343 89.78054
"2" "DA" 16.59264 14.764 14.9968 14.36513 91.08672
"3" "UMR80" 16.28646 15.88403 14.01783 15.96327 94.55977
"4" "UMR" 16.46229 15.87505 14.34763 15.87903 94.83926
"5" "MR50" 16.61305 16.04243 14.85003 16.15599 96.20576
> data
X merge A1 A2 K sum
1 DR 15.33559 14.74990 14.75560 14.32343 89.78054
2 DA 16.59264 14.76400 14.99680 14.36513 91.08672
3 UMR80 16.28646 15.88403 14.01783 15.96327 94.55977
4 UMR 16.46229 15.87505 14.34763 15.87903 94.83926
5 MR50 16.61305 16.04243 14.85003 16.15599 96.20576
My solution is to use arguments Rowv=FALSE and Colv=FALSE:
library(gplots)
library(RColorBrewer)
rnames <- data[,1]
mat_data <- data.matrix(data[,3:ncol(data)-1])
rownames(mat_data) <- rnames
my_palette <- colorRampPalette(c("red", "yellow", "green"))(n = 299)
col_breaks = c(seq(-1,0,length=100), # for red
seq(0,0.8,length=100), # for yellow
seq(0.81,1,length=100)) # for green
heatmap.2(mat_data,
main = "Rank", # heat map title
notecol="black", # change font color of cell labels to black
density.info="none", # turns off density plot inside color legend
trace="none", # turns off trace lines inside the heat map
margins =c(7,5), # widens margins around plot
col=my_palette, # use on color palette defined earlier
Rowv=FALSE,
Colv=FALSE,
dendrogram="none") # turn off column clustering
The heatmap is:

how to calculate the gradient with multiple dimensions of colors in R

this is related to this question but perhaps a simpler example. i'm curious if there's a reasonable way to calculate a multi-dimensional color gradient given three or four arbitrary colors the way that the r rgb() function does with red, green, blue? the one-dimensional gradient is easy (fig 1) but then it's unclear to me how to compute the two-dimensional gradient (fig 2) inside the triangle. edges are easy. it's what inside that counts
# one dimensional color gradient
one.dimensions <- colorRampPalette( c( "orange" , "blue" ) )( 100 )
plot( 1:100 , rep( 1 , 100 ) , col = one.dimensions , cex = 3 , pch = 16 , main = 'one dimensional gradient' )
# here are the edges of a three-colored triangle
dimensions13 <- colorRampPalette( c( "orange" , "blue" ) )( 100 )
dimensions12 <- colorRampPalette( c( "orange" , "red" ) )( 100 )
dimensions23 <- colorRampPalette( c( "blue" , "red" ) )( 100 )
plot( 1:100 , c( 1:50 , 50:1 ) , type = 'n' , main = 'two dimensional gradient' )
points( 1:100 , rep( 1 , 100 ) , col = dimensions12 , cex = 3 , pch = 16 )
points( seq( 1 , 50 , length = 100 ) , seq( 1 , 50 , length = 100 ) , col = dimensions13 , cex = 3 , pch = 16 )
points( seq( 50 , 100 , length = 100 ) , seq( 50 , 1 , length = 100 ) , col = dimensions23 , cex = 3 , pch = 16 )
you could consider three basic colour mixing strategies:
1- subtractive, using the alpha transparency blending of R graphics. Basically, superimpose multiple layers with their own gradient.
library(grid)
grid.newpage()
grid.raster(scales::alpha(colorRampPalette(c("white","blue"))(10), 0.3),
width=1,height=1)
grid.raster(t(scales::alpha(colorRampPalette(c("white","red"))(10), 0.3)),
width=1,height=1)
One drawback is that the final colour depends on the order of the layers.
The CMYK colour model could be another source of inspiration.
2- additive. I came up with a naive implementation as follows. Consider your N basic colours (say yellow, green, orange). Assign them a wavelength of the visible spectrum (570nm, 520nm, 600nm). Each colour is given a weight according to the position in the triangle (think of N lasers with tunable intensity). Now to get the colour associated with this mixture of N laser sources, you need to convolve with CIE colour matching functions. It's a physically sound mixing, mapping numbers to a visual perception. However, there's clearly an issue of uniqueness: several combinations will likely produce the same colour. The eye has only three different types of receptors after all, so N>3 is never going to result in a bijection.
3- pixelated (halftoning). Divide the image into small adjacent regions, like LCD screens, and every pixel is divided into N subpixels, each with its own colour. From far away and/or sufficient screen/print resolution, the eye won't see the details and will blur the adjacent colours for you.

Plotting raster images using custom colours in R

This might sound like a strange process, but its the best I can think of to control rasterised colour gradients with respect to discrete objects (points, lines, polygons). I'm 95% there but can't quite plot correctly.
This should illustrate proof of concept:
require(raster)
r = matrix(56:255, ncol=20) # reds
b = t(matrix(56:255, ncol=10)) # blues
col = matrix(rgb(r, 0, b, max=255), ncol=20) # matrix of colour strings
ras = raster(r) # data raster object
extent(ras) = extent(1,200,1,100) # set extent for aspect
plot(ras, col = col, axes=F, asp=T) # overwrite data with custom colours
Here I want to clip a raster to a triangle and create colour gradient of pixels inside based on their distances to one of the sides. Sorry for length but its the most minimal example I can design.
require(raster); require(reshape2); require(rgeos)
# equilateral triangle
t_s = 100 # half side
t_h = floor(tan(pi*60/180) * t_s) # height
corners = cbind(c(0, -t_s, t_s, 0), c(t_h, 0, 0, t_h))
trig = SpatialPolygons(list(Polygons(list(Polygon(corners)),"triangle")))
# line to measure pixel distances to
redline = SpatialLines(list(Lines(Line(corners[1:2,]), ID='redline')))
plot(trig); plot(redline, add=T, col='red', lwd=3)
# create a blank raster and clip to triangle
r = raster(mat.or.vec(nc = t_s*2 + 1, nr = t_h))
extent(r) = extent(-t_s, t_s, 0, t_h)
r = mask(r, trig)
image(r, asp=T)
# extract cell coordinates into d.f.
cells = as.data.frame(coordinates(rasterToPoints(r, spatial=T)))
# calculate distance of each pixel to redline with apply
dist_to_line = function(xy, line){
point = readWKT(paste('POINT(', xy[1], xy[2], ')'))
gDistance(point, line) / t_h
}
cells$dists = apply(cells, 1, dist_to_line, line=redline)
cells$cols = rgb(1 - cells$dists, 0, 0)
length(unique(cells$cols)) # count unique colours
# use custom colours to colour triangle pixels
image(r, col = cells$cols, asp=T)
plot(r, col = cells$cols, asp=T)
As you can see the plotting fails to overwrite as in the first example, but the data seems fine. Trying to convert to matrix also fails:
# try convertying colours to matrix
col_ras = acast(cells, y~x, value.var='cols')
col_ras = apply(col_ras, 1, rev) # rotate acw to match r
plot(r, col = col_ras, asp=T)
Very grateful for any assistance on what's going wrong.
Edit:
To show Spacedman's plotRGB method:
b = brick(draster, 1-draster, 1-draster)
plotRGB(b, scale=1)
plot(trig, col=NA, border='white', lwd=5, add=T)
Easy way is to go from your points to a spatial pixels data frame to a raster, then do the colour mapping...
Start with:
> head(cells)
x y dists
1 0.0000000 172.5 0.0014463709
2 0.0000000 171.5 0.0043391128
3 -0.9950249 170.5 0.0022523089
4 0.0000000 170.5 0.0072318546
5 0.9950249 170.5 0.0122114004
convert:
> coordinates(cells)=~x+y
> draster = raster(as(cells,"SpatialPixelsDataFrame"))
colourise:
> cols=draster
> cols[!is.na(draster)]= rgb(1-draster[!is.na(draster)],0,0)
> plot(cols, col=cols)
I'm not sure this is the right way to do things though, you might be better off creating an RGB raster stack and using plotRGB if you want fine colour control.

3d scatterplot with colored spheres with R and Rgl

I want to create a 3d scatter plot of spheres with their color being the fourth dimension.
I have the data in a csv file where each line indicates the x,y,z position of a particle and I have a column which tells me the value of the particle (1,2 or 3). I want to color the balls in one color if their value is 1 or in another color otherwise.
Edit:
I created the following code:
library(rgl)
m <- read.csv(file="mem0.csv", sep = ",", head=TRUE)
mcol = m$val
i = 1
mdim = dim(m)
while (i <= mdim[1] ){
if (mcol[i] == 1){
mcol[i] = "red"
}else {
mcol[i] = "blue"
}
i = i +1
}
plot3d(m$x, m$y, m$z, col = mcol, type='s', size=0.1)
Edit number 2:
I use the rgl.snapshot() to export to an svg file:
The data should display a layer of red balls, 4 layers of blue balls and a layer of red balls again.
The plot3d() function of the rgl package allows to do such a thing quite easily. And you can even explore your plot interactively :
R> library(rgl)
R> df <- data.frame(x=runif(10,0,1),
+ y=runif(10,0,1),
+ z=runif(10,0,1),
+ color=round(runif(10,1,3)))
R> df
x y z color
1 0.73518229 0.1385970 0.69053482 2
2 0.88789302 0.6872121 0.54734176 2
3 0.79402546 0.5771570 0.89613292 1
4 0.19922140 0.2117405 0.25116078 1
5 0.31825325 0.7449661 0.01174593 2
6 0.64614521 0.4704698 0.68905621 1
7 0.15242295 0.6461338 0.77896858 1
8 0.32698024 0.4548752 0.33969754 3
9 0.00793849 0.6557488 0.75901935 2
10 0.20460232 0.9302882 0.23413984 3
You can call plot3d() like this :
R> plot3d(df$x, df$y, df$z, col=df$color, size=2, type='s')
Which will give you something like :

Resources