I'm trying to determine if it's possible to display the underlying data points on a Gadfly chart. I know that I can display the labels associated with a particular point, but how can I show the actual values on the chart, itself?
For example, from the Gadfly documentation, let's say I have this chart:
plot(x=rand(10), y=rand(10))
How can I display the resulting values in the x and y vectors on the chart itself?
Actually, it's easy to get a string representation, e.g. string(3).
How about the following:
using Gadfly
N = 10
xx = rand(1:10, N) # N random integers between 1 and 10
yy = rand(1:10, N)
labels = map(string, zip(x,y))
plot(x=xx, y=yy, label=labels, Geom.label, Geom.point)
This gives something like the following:
One way to do this is to feed the values into Gadfly via a labels string vector:
label_vec = ["4", "4", "7", "7", "9", "1", "8", "10", "11", "2"]
plot(x=rand(10), y=rand(10), Labels = label_vec, Geom.label)
It's a pain to parse ints/floats into strings though, it would be nice if you could feed them directly into Gadfly as ints/floats.
Does anyone have a better way?
Related
I created an object of class cca in vegan and now I am trying to tidy up the triplot. However, I seemingly can't use the select argument to only show specified items.
My code looks like this:
data("varechem")
data("varespec")
ord <- cca(varespec ~ Al+S, varechem)
plot(ord, type = "n")
text(ord, display = "sites", select = c("18", "21"))
I want only the two specified sites (18 and 21) to appear in the plot, but when I run the code nothing happens. I do not even get an error meassage.
I'm really stuck, but I am fairly certain that this bit of code is correct. Can someone help me?
I can't recall now, but I don't think the intention was to allow "names" to select which rows of the scores should be selected. The documentation speaks of select being a logical vector, or indices of the scores to be selected. By indices it was meant numeric indices, not rownames.
The example fails because select is also used to subset the labels character vector of values to be plotted in text(), and this labels character vector is not named. Using a character vector to subset another vector requires that the other vector be named.
Your example works if you do:
data("varechem")
data("varespec")
ord <- cca(varespec ~ Al + S, varechem)
plot(ord, type = "n")
take <- which(rownames(varechem) %in% c("18", "21"))
# or
# take <- rownames(varechem) %in% c("18", "21")
text(ord, display = "sites", select = take)
I'll have a think about whether it will be simple to support the use case of your example.
The following code probably gives the result you want to achieve:
First, create an object to store the blank CCA1-CCA2 plot
p1 = plot(ord, type = "n")
Find and then save the coordinates of the sites 18 and 21
p1$p1$sites[c("18", "21"),]
# CCA1 CCA2
#18 0.3496725 -1.334061
#21 -0.8617759 -1.588855
site18 = p1$sites["18",]
site21 = p1$sites["21",]
Overlay the blank CCA1-CCA2 plot with the points of site 18 and 21. Setting different colors to different points might be a good idea.
points(p1$sites[c("18", "21"),], pch = 19, col = c("blue", "red"))
Showing labels might be informative.
text(x = site18[1], y = site18[2] + 0.3, labels = "site 18")
text(x = site21[1], y = site21[2] + 0.3, labels = "site 21")
Here is the resulted plot.
I am learning the Julia from the coursera
using DelimitedFiles
EVDdata = DelimitedFiles.readdlm("wikipediaEVDdatesconverted.csv", ',')
# extract the data
epidays = EVDdata[:,1]
EVDcasesbycountry = EVDdata[:, [4, 6, 8]]
# load Plots and plot them
using Plots
gr()
plot(epidays, EVDcasesbycountry)
I am getting the error message Cannot convert Array{Any,2} to series data for plotting
but in that course the lecturer successfully plots the data. where I am going wrong?
I search about the error where I end up something call parsing the string into an integer. As the data set may contain string values.
Or am I missing something else.
I found this to be working for me:
# extract the data
epidays = Array{Integer}(EVDdata[:,1])
EVDcasesbycountry = Array{Integer}(EVDdata[:, [4, 6, 8]])
# load Plots and plot them
using Plots
gr()
plot(epidays, EVDcasesbycountry)
It's a bit hard to tell what's going on in Coursera, as it's not clear what versions of Plots and DataFrames the video is using.
The error you're seeing however is telling you that a 2-dimensional Array (i.e. a matrix) can't be converted to a single series for plotting. This is because plot is supposed to be called with two vectors, one for x and one for y values:
plot(epidays, EVData[:, 4])
You can plot multiple columns in a loop:
p = plot()
for c in eachcol(EVData[:, [4, 6, 8]])
plot!(p, epidays, c)
end
display(p)
There is also StatsPlots.jl, which extend the standard Plots.jl package for frequently needed "data science-y" plotting functions. In this case you could use the #df macro for plotting DataFrames; just quoting one of the examples in the Readme:
using DataFrames, IndexedTables
df = DataFrame(a = 1:10, b = 10 .* rand(10), c = 10 .* rand(10))
#df df plot(:a, [:b :c], colour = [:red :blue])
Finally, there are some more grammar-of-graphics inspired plotting packages in Julia which are focused on plotting DataFrames, e.g. the pure-Julia Gadfly.jl, or the VegaLite wrapper VegaLite.jl
You can also try this
using StatsPlots
gr()
using DataFrames, IndexedTables
df = DataFrame(EVDdata)
#df df plot(:x1, [:x4 :x6 :x8], marker = ([:octagon :star7 :square], 9), title = "EVD in West Africa, epidemic segregated by country", xlabel = "Days since 22 March 2014",ylabel = "Number of cases to date",line = (:scatter), colour = [:red :blue :black])
On the other hand, this tutorial does (apparently) the same thing as the coursera plot and it works.
https://docs.juliaplots.org/latest/tutorial/#Basic-Plotting:-Line-Plots
x = 1:10; y = rand(10, 2) # 2 columns means two lines
plot(x, y)
And I haven't figured out why too...
Update: The staff answer is that maybe " Julia no longer supports plot 'Array{Any,2}' " and a simple workaround is to convert the EVDcasesbycountry data to Int doing this:
epidays = EVDdata[:,1]
EVDcasesbycountry = convert.(Int, EVDdata[:, [4, 6, 8]])
It worked for me and is kinda consistant with my first answer because when I checked the types of x and y they weren't Any as the data of epidays and EVDcasesbycountry.
https://docs.juliaplots.org/latest/generated/gr/
This contains some nice examples
Coming to the problem you can pass vector instead on the matrix for plotting
using Plots
gr()
y = Vector[EVData[:,4],EVData[:,6],EVData[:,8]]
plot(
epidays,y,
color = [:black :orange :red],
line = (:scatter),
marker = ([:hex :d :star4],5)
)
I have two sets of rasterstacks (each with a few hundred raster layers) - the first is a rasterstack containing a set of sensored time series images (with gap) and a second stack of temporally interpolated images for the gaps of the first set. Naming of the layers in each set is according to the day they where measured/or interpolated, starting from day 1....n
I now want to combine these two sets into one ordered (from 1 to n according to layer name) rasterstack. I have looked into different ways of doing this but haven't been able to get the results;
A way to order the layers within a rasterstack (for example by using something like this (comb_r is the raster stack from my reproducible example below). This reorders the names but not the entire layers:
names(comb_r)<-comb_r[order(names(comb_r))]
create two lists of layers in both stacks using the unstack function and than create a combined ordered list as an input to a new stack operation (did not get this to work).
finally I guess I could save all layers onto the hard disk and than reassemble a stack from there (considering the many layers probably not the best way forward).
Any suggestions on how to proceed would be welcome. I have added a toy example of my problem here:
library(raster)
r1 <- raster(matrix(runif(9), ncol = 3))
r2 <- raster(matrix(runif(9), ncol = 3))
r3 <- raster(matrix(runif(9), ncol = 3))
r4 <- raster(matrix(runif(9), ncol = 3))
r5 <- raster(matrix(runif(9), ncol = 3))
r <- stack(r1, r2, r3,r4,r5)
names(r)<-c(1,4,6,8,10)
r6 <- raster(matrix(runif(9), ncol = 3))
r7 <- raster(matrix(runif(9), ncol = 3))
r8 <- raster(matrix(runif(9), ncol = 3))
r9 <- raster(matrix(runif(9), ncol = 3))
r10 <- raster(matrix(runif(9), ncol = 3))
rr <- stack(r6,r7,r8,r9,r10)
names(rr)<-c(2,3,5,7,9)
comb_r<-stack(r,rr)
Can you not just take a 'subset' in a different order:
subset(comb_r, order(c(1,4,6,8,10,2,3,5,7,9)))
You can choose the second argument of 'subset' to reflect your desired ordering - the one you've given is slightly odd, in that it takes one from r, then two from rr, then alternates from r and rr.
Calling order within the subset function did not work for me.
I used the following:
subset(comb_r, c(1,4,6,8,10,2,3,5,7,9))
This should works:
ReorderStack<- stack(comb_r[[1]],comb_r[[4]],comb_r[[6]],comb_r[[8]],comb_r[[10]],
comb_r[[2]], comb_r[[3]],comb_r[[5]],comb_r[[7]],comb_r[[9]])
If your rasters are already named you can just order them like so:
ordered_names <- c("1", "2", "3", "4", "5", "6", "7", "8", "9", "10")
ordered_stack <- comb_r[[ordered_names]]
I have a function get.single.plot, which takes one character argument and returns a ggplot2 plot object. I would like to build a grid.arrange object with n plots on it, where the n is the size of vector of (mentioned) character arguments.
E.g., I woould like something like this to work:
character.argument.vector <- c("12", "1", "2")
grid.arrange(unlist(lapply(character.argument.vector, function(n) get.single.plot(n))),
ncol = 1)
Such thing does not work - I receive the following information:
Error in arrangeGrob(..., as.table = as.table, clip = clip, main = main, :
input must be grobs!
How should I do it?
With gridExtra v>=2.0 you can simply pass a list of grobs (or plots) to grid.arrange,
grid.arrange(grobs = lapply(...), ncol=1)
I have a bar chart with text labels along the x-axis. Some of the labels are quite lengthy and I would like to make them look neater. Any ideas of how I might achieve that?
library(sjPlot)
require(ggplot2)
require(ggthemes)
WAM_3_plot <- sjp.frq(WAM_Dec13_R2$WAM_3, title= c("WAM Item 3"),
axisLabels.x=c("Disruptive behaviour can be contained and does not spread to other patients. Generally, behaviour on the ward is positive and pro-therapeutic.",
"1", "2","3","4",
"Disruptive behaviour by one patient tends to spread to other patients and is only contained with great difficulty. The general level of behaviour seems to be getting more counter-therapeutic."),
barColor = c("palegreen4", "palegreen3", "palegreen2", "brown1", "brown2", "brown3"),
upperYlim = 25,
valueLabelSize = 5,
axisLabelSize = 1.2,
breakLabelsAt=14, returnPlot=TRUE)
WAM_3_plot + theme(axis.text.x=element_text(hjust=0.5))
Like this?
Since you didn't provide any data, we have no way of knowing what your attempt looks like, but this seems like it might be close. The main feature is the use of strwrap(...) to insert CR (\n) into your labels.
set.seed(1)
library(ggplot2)
axisLabels.x <- c("Disruptive behaviour can be contained and does not spread to other patients. Generally, behaviour on the ward is positive and pro-therapeutic.",
"1", "2","3","4",
"Disruptive behaviour by one patient tends to spread to other patients and is only contained with great difficulty. The general level of behaviour seems to be getting more counter-therapeutic.")
labels.wrap <- lapply(strwrap(axisLabels.x,50,simplify=F),paste,collapse="\n") # word wrap
gg <- data.frame(x=LETTERS[1:6], y=sample(1:10,6))
ggplot(gg) +
geom_bar(aes(x,y, fill=x), stat="identity")+
scale_x_discrete(labels=labels.wrap)+
scale_fill_discrete(guide="none")+
labs(x="",y="Response")+
coord_flip()
You may change the breakLabelsAt parameter, decrease the axisLabelSize and set flipCoordinates to TRUE, then you get similar results. I used the efc-sample data set which is included in the sjPlot-package:
data(efc)
sjp.frq(efc$e42dep, title=c("WAM Item 3"),
axisLabels.x=c("Disruptive behaviour can be contained and does not spread to other patients. Generally, behaviour on the ward is positive and pro-therapeutic.",
"1", "2",
"Disruptive behaviour by one patient tends to spread to other patients and is only contained with great difficulty. The general level of behaviour seems to be getting more counter-therapeutic."),
valueLabelSize=5,
axisLabelSize=.8,
breakLabelsAt=50,
flipCoordinates=T)
Rotating the axis labels can help a lot:
theme(axis.text.x = element_text(angle=90, vjust=0.5))