Related
I have the following code:
# package for ploting functions
using Plots
# use GR
gr()
# nb points to plot
nbPts = 22
# define polar coordinates of a 30 degree (pi/6) rotation
sine = sin(pi/6)
cosine = cos(pi/6)
# scale factor
scale_factor = 0.9
#---------------------------------------
# 1. PLOT POINTS USING ROTATION MATRIX
#---------------------------------------
# define Rotation matrix ( angle = pi/6, center = (0, 0) )
R = zeros(Float64, 2, 2)
R[1,1] = R[2,2]= cosine
R[1,2] = -sine
R[2,1] = sine
# Scale matrix
### ... <-- EXERCISE 4(c): define a uniform scaling matrix (use scale_factor)
# arrays of points coords
X_mat = zeros(nbPts)
Y_mat= zeros(nbPts)
# first Point (1,0)
X_mat[1] = 1.0
Y_mat[1] = 0.0
for i in 2:nbPts
prevPoint = [X_mat[i-1], Y_mat[i-1]]
#apply rotation to previous point to obtain new point
newPoint = R * prevPoint
### ... <-- EXERCISE 4(c): apply scaling matrix
X_mat[i] = newPoint[1]
Y_mat[i] = newPoint[2]
end
# plot points in blue
plt1 = scatter(X_mat, Y_mat, color=:blue, xlim = (-1.1, 1.1), ylim = (-1.1, 1.1), label=false, title="Rotation using matrices" );
#---------------------------------------
# 2. PLOT POINTS USING COMPLEX NUMBERS
#---------------------------------------
function ComplexProduct(z, w)
(((z[1]*w[1])+(z[2]*w[2])),((z[1]*w[2])+(z[2]*w[1])))
### ... <-- EXERCISE 4(b): implement complex product z * w
end
# first point: z = 1 + 0 * i
Z = ( 1.0, 0.0 )
# second point: w = cosine( pi/6) + sine( pi/6) * i
W = ( cosine, sine )
### ... <-- EXERCISE 4(c): apply scale_factor to W
# arrays of points coords
X_comp = zeros(nbPts)
Y_comp = zeros(nbPts)
# first Point (1,0)
X_comp[1] = Z[1]
Y_comp[1] = Z[2]
for i in 2:nbPts
prevPoint = (X_comp[i-1], Y_comp[i-1])
newPoint = ComplexProduct(prevPoint[1], prevPoint[2]) ### <-- EXERCISE 4(b): compute newPoint by applying rotation to prevPoint (use complex product)
X_comp[i] = newPoint[1]
Y_comp[i] = newPoint[2]
end
# plot points in red
plt2 = scatter(X_comp, Y_comp, color=:red, xlim = (-1.1, 1.1), ylim = (-1.1, 1.1), label=false, title="Rotation using complex numbers" );
# arrange and display
display( plot( plt1, plt2, layout = (1, 2), size=(600*2, 600) ))
The Error:
The Thing I want:
I have to implement a product of complex numbers and this should be used to calculate the rotation with complex numbers.
Should look like that:
What do I have to change so that the BoundsError is fixed?
Don't know what exactly i do wrong because of the poorly information i get from this error log.
Greetings and thanks for the help.
prevPoint[1] is a scalar while your function ComplexProduct expects something that has 2 elements. Perhaps you wanted to pass prevPoint instead of prevPoint[1]?
BTW you use incorrect naming pattern. CamelNaming is discouraged for Julia.
Your variable should be named prev_point and your function should be named complex_product.
Fixed the bug by changing the following code:
newPoint = ComplexProduct(prevPoint, W)
in line 92
Polygon
I have a polygon that has only 90 and 45-degree angles, now I want to change the length of any side and adjust the polygon so that results should be a similar polygon.
Like this:
Shape after side change
import numpy as np
import matplotlib.pyplot as plt
# an arbitrary polygon, for example a pentagon:
P = np.array([[0.2, 0.1], [1, -0.2], [3, 1], [2, 0.7], [0.5, 1], [0.2, 0.1]])
P[-1, ] = P[0, ]
# pick a side between, say the one between vertices P[i,] and P[i+1,],
# and assume you want to make it of length a = 3:
i=2
a=3
# pick a point V0 in the plane, where a vertex P[j,] of the scaled polygon should be places:
j=1
v0 = [1,1]
# calculate the scale, which is a / (length of edge P[i,] P[i+1,]):
scale = a / np.linalg.norm(P[i+1, ] - P[i,])
# scale and position the polygon where you want it to be:
P_scaled = scale * P + (v0 - P[j,])
# plot polygon P:
plt.figure()
plt.plot(P[:,0], P[:,1])
for k in range(P.shape[0]):
plt.plot(P[k,0], P[k,1], 'ro')
# plot polygon P_scaled:
plt.plot(P_scaled[:,0], P_scaled[:,1])
for k in range(P_scaled.shape[0]):
plt.plot(P_scaled[k,0], P_scaled[k,1], 'ro')
axx = plt.gca()
axx.set_aspect('equal')
plt.show()
I'd like to make a three-panel figure with each panel containing grouped barplots . And for the third panel I'd like to make the plot stacked. I've found excellent code here: Simplest way to do grouped barplot. I can get everything except for the stacked plot using the elegant solution at the end of this entry.
I tried many iterations of base R code to get a stacked barplot, but kept running into issues with having a dataframe and not a matrix or vector for the height argument. When I converted to a matrix though I lost the factors in my data. I'll put my working code for the other plots below and indicate where I'd like to add the stacked variable.
Here is a sample of my data
Population Sex numsnpsused numoutliers percentoutliers numoutspc1 numoutspc2
all f_and_m 8728 70 0.80 55 15
all f 6613 11 0.17 9 2
all m 9958 151 1.52 91 60
south f_and_m 7358 51 0.69 15 36
south f 6547 65 0.99 17 48
south m 8068 69 0.86 18 51
Code:
bar <- function(dv, factors, dataframe, percentage=FALSE, errbar=!percentage, half.errbar=TRUE, conf.level=.95,
xlab=NULL, ylab=NULL, main=NULL, names.arg=NULL, bar.col="black", whisker=.015,args.errbar=NULL,
legend=TRUE, legend.text=NULL, args.legend=NULL,legend.border=FALSE, box=TRUE, args.yaxis=NULL,
mar=c(5,4,3,2),...){
axes=!percentage
dv.name<-substitute(dv)
if(length(dv.name)>1) stop("'dv' only takes one variable")
dv.name<-as.character(dv.name)
dv<-dataframe[[dv.name]]
fnames<-substitute(factors)
if(length(fnames)==1){
factors<-as.character(fnames)
nf<-1
}else{
factors<-as.character(fnames[-1L])
nf<-length(factors)
}
if(nf>2) stop("This function accepts no more than 2 factors \n",
"\t-i.e., it only plots one-way or two-way designs.")
if(percentage & errbar){
warning("percentage=TRUE; error bars were not plotted")
errbar<-FALSE
}
if(!percentage) xbars<-tapply(dv, dataframe[,factors], mean, na.rm=TRUE)
else {
xbars<-tapply(dv, list(interaction(dataframe[,factors], lex.order=TRUE)), mean, na.rm=TRUE)
if(sum(na.omit(dv)!=0&na.omit(dv)!=1)>0)
stop("Data points in 'dv' need to be 0 or 1 in order to set 'percentage' to TRUE")
xbars<-rbind(xbars, 1-xbars)*100
}
if(errbar){
se<-tapply(dv, dataframe[,factors], sd, na.rm=TRUE)/sqrt(tapply(dv, dataframe[,factors], length))
conf.level=1-(1-conf.level)/2
lo.bar<-xbars-se*qnorm(conf.level)
hi.bar<-xbars+se*qnorm(conf.level)
}
extras<-list(...)
if(legend & !percentage){
if(is.null(legend.text))
legend.text<-sort(unique(dataframe[[factors[1]]]))
args.legend.temp<-list(x="topright", bty=if(!legend.border)"n" else "o",
inset=c(0,0))
if(is.list(args.legend))
args.legend<-modifyList(args.legend.temp, args.legend)
else
args.legend<-args.legend.temp
} else if(legend & percentage){
if(is.null(legend.text))
legend.text<-c("1", "0")
args.legend.temp<-list(x="topright", bty=if(!legend.border)"n" else "o",
inset=c(0,0))
if(is.list(args.legend))
args.legend<-modifyList(args.legend.temp, args.legend)
else
args.legend<-args.legend.temp
} else if(!legend){
args.legend<-NULL
legend.text<-NULL
}
if(errbar && legend && !percentage) ymax<-max(hi.bar)+max(hi.bar)/20
else if(errbar && legend && percentage) ymax<-115
else if(errbar && !legend) ymax <- max(xbars)
else if(!errbar && legend && percentage) ymax<-110
else if(!errbar) ymax<-max(xbars) + max(xbars)/20
if(!percentage){
args.barplot<-list(beside=TRUE, height=xbars, ylim=c(0, ymax), main=main, names.arg=names.arg,
col=hcl(h=seq(0,270, 270/(length(unique(dataframe[[factors[1]]]))))[-length(unique(dataframe[[factors[1]]]))]),
legend.text=legend.text, args.legend=args.legend, xpd=TRUE,
xlab=if(is.null(xlab)) factors[length(factors)] else xlab,
ylab=if(is.null(ylab)) dv.name else ylab, axes=axes)
}else{
args.barplot<-list(beside=TRUE, height=xbars, ylim=c(0, ymax), main=main, names.arg=names.arg,
col=hcl(h=seq(0,270, 270/(length(unique(dataframe[[factors[1]]]))))[-length(unique(dataframe[[factors[1]]]))]),
legend.text=legend.text, args.legend=args.legend, xpd=TRUE,
xlab=if(is.null(xlab)) " "[length(factors)] else xlab,
ylab=if(is.null(ylab)) "percentage" else ylab, axes=axes)
}
args.barplot<-modifyList(args.barplot, extras)
errbars = function(xvals, cilo, cihi, whisker, nc, args.errbar = NULL, half.errbar=TRUE) {
if(half.errbar){
cilo<-(cihi+cilo)/2
}
fixedArgs.bar = list(matlines, x=list(xvals),
y=lapply(split(as.data.frame(t(do.call("rbind",
list(cihi, cilo)))),1:nc),matrix,
nrow=2, byrow=T))
allArgs.bar = c(fixedArgs.bar, args.errbar)
whisker.len = whisker*(par("usr")[2] - par("usr")[1])/2
whiskers = rbind((xvals - whisker.len)[1,],
(xvals + whisker.len)[1,])
fixedArgs.lo = list(matlines, x=list(whiskers),
y=lapply(split(as.data.frame(t(do.call("rbind",
list(cilo, cilo)))), 1:nc), matrix, nrow=2, byrow=T))
allArgs.bar.lo = c(fixedArgs.lo, args.errbar)
fixedArgs.hi = list(matlines, x=list(whiskers),
y=lapply(split(as.data.frame(t(do.call("rbind",
list(cihi, cihi)))), 1:nc), matrix, nrow=2, byrow=T))
allArgs.bar.hi = c(fixedArgs.hi, args.errbar)
invisible(do.call(mapply, allArgs.bar))
if(!half.errbar) invisible(do.call(mapply, allArgs.bar.lo))
invisible(do.call(mapply, allArgs.bar.hi))
}
par(mar=mar)
errloc<-as.vector(do.call(barplot, args.barplot))
if(errbar){
errloc<-rbind(errloc, errloc)
lo.bar<-matrix(as.vector(lo.bar))
hi.bar<-matrix(as.vector(hi.bar))
args.errbar.temp<-list(col=bar.col, lty=1)
args.errbar<-if(is.null(args.errbar)|!is.list(args.errbar))
args.errbar.temp
else if(is.list(args.errbar))
modifyList(args.errbar.temp, args.errbar)
errbars(errloc, cilo=lo.bar, cihi=hi.bar, nc=1, whisker=whisker,
args.errbar=args.errbar, half.errbar=half.errbar)
}
if(box) box()
if(percentage){
args.yaxis.temp<-list(at=seq(0,100, 20), las=1)
args.yaxis<-if(!is.list(args.yaxis)) args.yaxis.temp else modifyList(args.yaxis.temp, args.yaxis)
do.call(axis, c(side=2, args.yaxis))
}
}
bar(dv = numsnpsused,
factors = c(Sex, Population),
dataframe = WALL,
errbar = FALSE,
col=c("red","purple","blue"),
ylab=c("Number of SNPs used in analysis"),
ylim=c(0, 12000)) #I increased the upper y-limit to accommodate the legend.
parpar(mfrow=c(2,2))
bar(dv = percentoutliers,
factors = c(Sex, Population),
dataframe = WALL,
errbar = FALSE,
col=c("red","purple","blue"),
ylab=c("% of SNPs that were outliers"),
ylim=c(0,3)) #I increased the upper y-limit to accommodate the legend.
##I want to include a second variable to stack in this plot
bar(dv = numoutspc1,
factors = c(Sex, Population),
dataframe = WALL,
errbar = FALSE,
col=c("red","purple","blue"),
ylab=c("Number of outliers associated with each PCaxis"),
ylim=c(0, 240)) #I increased the upper y-limit to accommodate the legend.
Here is the plot that I made
It's hard to provide a good answer without more details and what graph you expect as output. Here is a solution using ggplot2 that might start you off. You can imitate the grouped bar plot by merging the two grouping variables while still stacking by another variable.
df <- data.frame(y=sample(c(2000:2002),1000,T), k=sample(letters[1:3],1000,T),
g=sample(c(1:2),1000,T),
c=sample(c('t','f'),1000,T),stringsAsFactors = F)
df %>% count(y,k,g,c) %>% mutate(k1=paste0(k,g)) %>%
filter(y==2002|c!='f') %>%
ggplot(aes(k1,n,fill=c)) + geom_bar(stat='identity') + facet_wrap(~y)
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.
I have a data that looks like this:
> print(dat)
cutoff tp fp
1 0.6 414 45701
2 0.7 172 16820
3 0.8 51 4326
4 0.9 49 3727
5 1.0 0 0
I want to plot them in reverse-order from smallest dat$tp to largest.
However this code plot them in order like above (i.e. largest to smallest) instead.
> fp_max <- max(dat$fp);
> tp_max <- max(dat$tp);
> op <- par(xaxs = "i", yaxs = "i")
> plot(tp ~ fp, data = dat, xlim = c(0,fp_max),ylim = c(0,tp_max), type = "n")
> with(dat, lines(c(0, fp, fp_max), c(0, tp, tp_max), lty=1, type = "l", col = "black"))
> lines( par()$usr[1:2], par()$usr[3:4], col="red" )
How can I modify the code above to address the problem?
Of course, the x-axis & y-axis coordinates should be from smallest to largest value
The following shows the result of my current code.
Notice that the line started at 0,0 and it 'goes back' to 0 again.
we want to avoid it going back to 0.
Ahh, I understand.
It's because lines draws lines between the points in the order they are given.
There are a few ways you could get around this:
do type='l' in your plot command and then with(dat,lines(...)) is not necessary:
# can also do the col='black',lty=1 in here.
plot(tp ~ fp, data = dat, xlim = c(0,fp_max),ylim = c(0,tp_max), type = "l")
Note that by definition of your fp_max and tp_max, you will include the point (fp_max,tp_max) already. And as long as you have a row with (0,0) for tp and fp in dat, you'll also get the (0,0) point.
Sort dat$tp and use that to sort dat$fp too:
plot(tp ~ fp, ..., type='n')
# sort dat$tp
obj <- sort(dat$fp,index.return=T)
# use obj$x as tp and obj$ix to sort dat$fp prior to plotting
with(dat,
lines(c(0, obj$x, fp_max), c(0, tp[obj$ix], tp_max),
lty=1, type = "l", col = "black"))
#Get order of rows
idx <- order(dat$tp)
#Select data in sorted order
sorted <- dat[idx,]