How to change maker in scatter plot in Julia - plot

I would like to change the marker style of a 2D scatter plot based on the value in a vector, ultimately displaying 3 dimensions on two axes. Below is what I'd like to do and the error I get when I try it.
x = rand(1:30,100)
y = rand(20:30,100)
MyMarker = [fill("o",50);fill("x",50)]
scatter(x,y,marker=MyMarker,alpha=0.5)
LoadError: PyError (:PyObject_Call) <type 'exceptions.ValueError'>
ValueError(u"Unrecognized marker style ['o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x']",)
File "/home/lara/.julia/v0.4/Conda/deps/usr/lib/python2.7/site-packages/matplotlib/pyplot.py", line 3251, in scatter
edgecolors=edgecolors, data=data, **kwargs)
File "/home/lara/.julia/v0.4/Conda/deps/usr/lib/python2.7/site-packages/matplotlib/__init__.py", line 1812, in inner
return func(ax, *args, **kwargs)
File "/home/lara/.julia/v0.4/Conda/deps/usr/lib/python2.7/site-packages/matplotlib/axes/_axes.py", line 3877, in scatter
marker_obj = mmarkers.MarkerStyle(marker)
File "/home/lara/.julia/v0.4/Conda/deps/usr/lib/python2.7/site-packages/matplotlib/markers.py", line 171, in __init__
self.set_marker(marker)
File "/home/lara/.julia/v0.4/Conda/deps/usr/lib/python2.7/site-packages/matplotlib/markers.py", line 252, in set_marker
' {0}'.format(marker))
while loading In[91], in expression starting on line 1
in getindex at /home/lara/.julia/v0.4/PyCall/src/PyCall.jl:228
in pysequence_query at /home/lara/.julia/v0.4/PyCall/src/conversions.jl:717
[inlined code] from /home/lara/.julia/v0.4/PyCall/src/conversions.jl:733
in pytype_query at /home/lara/.julia/v0.4/PyCall/src/conversions.jl:762
in convert at /home/lara/.julia/v0.4/PyCall/src/conversions.jl:782
in pycall at /home/lara/.julia/v0.4/PyCall/src/PyCall.jl:363
in call at /home/lara/.julia/v0.4/PyCall/src/PyCall.jl:372
in close_queued_figs at /home/lara/.julia/v0.4/PyPlot/src/PyPlot.jl:401
I have tried the following, neither of which is exactly what I want to do but they are close enough, and neither works.
using Plots
pyplot(size=(400,200), legend=false) # set backend and set some session defaults
scatter(rand(30),m = ColorGradient([:red,:green,:blue]),zcolor = repmat([0,0.5,1],10))
using Plots
pyplot(size=(400,200), legend=false) # set backend and set some session defaults
scatter(rand(30),
m = ColorGradient([:red,:green,:blue]), # colors are defined by a gradient
zcolor = repmat([0,0.5,1],10) # sample from the gradient, cycling through: 0, 0.5, 1
)
Can anyone tell me how to make marker take in a vector?
Update
I have a work around but I don't like having to do this: dividing the data into separate sets and then plotting them on the same axes:
PyPlot.plot(spacerdataActualSpacer[:Length],spacerdataActualSpacer[:Curvature],marker="x",".")
PyPlot.plot(spacerdataNoActualSpacer[:Length],spacerdataNoActualSpacer[:Curvature],marker="o",".")

There's a few different things you can try (I'm on Plots dev, so I can't be certain what will work for you out of the box):
scatter(rand(30), group = repmat(1:3,10), marker=:auto)
scatter(rand(30), group = repmat(1:3,10), shape=[:+ :o :utri])
scatter(rand(30), group = repmat(1:3,10), shape=[:+ :o :utri], layout=(3,1))
Let me know if any of that is what you want. To be honest I'm not totally sure I know what your ideal viz will look like.

Related

How to open an image?

enter image description here
I use 'openImage' package to import multiple images,
#this sets the directory
list\<- list.files("C://Users//Bilal//Desktop//test//bb", all.files
= FALSE,full.names = TRUE)
#this loop to import the images
df<-data.frame()
#df <-list()
for (i in seq_along(lista)) {
pic<-readImage(lista[i])
pic<-rgb_2gray(pic)
pic<-resizeImage(pic, width = 48, height = 64)
pic<-as.vector(pic)
pre_pic<-t(pic)
df<-rbind(df,pre_pic)}
#this code is used to open the image but the second line does not work
#Error in image.default(df, xaxt = "n", yaxt = "n", col = grayscale) :
#'z' must be a matrix
grayscale <- gray(seq(0, 1, length = 100))
image(df[,,1], xaxt='n', yaxt='n', col=grayscale)
This is what I expect to see
I understand now what's happening; thanks for sharing the image. First- you were/are using grDevices::image() <- the base R function.
The error tells you that R can't determine how you shaped your data. When you flattened the matrix into a vector, you knew it was 48 x 64, but that information wasn't there when you sent it to image.
You could do either one of the following:
# before making it a vector
image(t(p3), col = grayscale, yaxt = 'n', xaxt = 'n')
# after making it a row in a data frame
image(t(matrix(unlist(df[1,]), ncol = 64, nrow = 48)),
col = grayscale, yaxt = 'n', xaxt = 'n')

R: Plotting 3D Objects in R (iris data)

I am using the R programming language. I am trying to follow this tutorial over here: http://www.semspirit.com/artificial-intelligence/machine-learning/regression/support-vector-regression/support-vector-regression-in-r/
For the famous Iris dataset, I am trying to plot the 3D decision surface for the random forest algorithm (using tsne dimensions):
library(Rtsne)
library(dplyr)
library(ggplot2)
library(plotly)
library(caret)
library(randomForest)
#data
a = iris
a <- unique(a)
#create two species just to make things easier
s <- c("a","b")
species<- sample(s , 149, replace=TRUE, prob=c(0.3, 0.7))
a$species = species
a$species = as.factor(a$species)
#split data into train/test, and then random forest
index = createDataPartition(a$species, p=0.7, list = FALSE)
train = a[index,]
test = a[-index,]
rf = randomForest(species ~ ., data=train, ntree=50, mtry=2)
#have the model predict the test set
pred = predict(rf, test, type = "prob")
labels = as.factor(ifelse(pred[,2]>0.5, "a", "b"))
confusionMatrix(labels, test$species)
#tsne algorithm
tsne_obj_3 <- Rtsne(test[,-5], perplexity=1, dims=3)
df_m2 <- as.data.frame(tsne_obj_3$Y)
df_m2$labels = test$species
From here, I am trying to plot the 3d decision surface (http://www.semspirit.com/artificial-intelligence/machine-learning/regression/support-vector-regression/support-vector-regression-in-r/) :
axis_1 = df_m2$V1
axis_2 = df_m2$V2
axis_3 = df_m2$V3
plot_ly(x=as.vector(axis_1),y=as.vector(axis_2),z=axis_3, type="scatter3d", mode="markers", name = "Obs", marker = list(size = 3)) %>%
add_trace(x=as.vector(axis_1),y=as.vector(axis_2),z=df_m2$labels, type = "mesh3d", name = "Preds")
But I am getting the following error:
2: In RColorBrewer::brewer.pal(N, "Set2") :
minimal value for n is 3, returning requested palette with 3 different levels
3: 'mesh3d' objects don't have these attributes: 'mode', 'marker'
Valid attributes include:
'type', 'visible', 'legendgroup', 'name', 'uid', 'ids', 'customdata', 'meta', 'hoverlabel', 'stream', 'uirevision', 'x', 'y', 'z', 'i', 'j', 'k', 'text', 'hovertext', 'hovertemplate', 'delaunayaxis', 'alphahull', 'intensity', 'intensitymode', 'color', 'vertexcolor', 'facecolor', 'cauto', 'cmin', 'cmax', 'cmid', 'colorscale', 'autocolorscale', 'reversescale', 'showscale', 'colorbar', 'coloraxis', 'opacity', 'flatshading', 'contour', 'lightposition', 'lighting', 'hoverinfo', 'showlegend', 'xcalendar', 'ycalendar', 'zcalendar', 'scene', 'idssrc', 'customdatasrc', 'metasrc', 'xsrc', 'ysrc', 'zsrc', 'isrc', 'jsrc', 'ksrc', 'textsrc', 'hovertextsrc', 'hovertemplatesrc', 'intensitysrc', 'vertexcolorsrc', 'facecolorsrc', 'hoverinfosrc', 'key', 'set', 'frame', 'transforms', '_isNestedKey', '_isSimpleKey', '_isGraticule', '_bbox'
A 3D plot is produced, but the 3D plane is completely gone.
Can someone please tell me what I am doing wrong?
I am trying to make so that when you move your mouse over each point, for that point it will display the value of a$Sepal.Length, a$Sepal.Width, a$Petal.Length, a$Petal.Width, a$Species
Thanks
When you called add_trace(), z is not assigned correctly. The labels won't plot; you need to plot the probabilities you identified, z=df_m2$pred.
There are multiple ways to fix the issues with the mesh plot, but the easiest would be to use add_mesh instead of add_trace.
plot_ly(x=as.vector(axis_1),
y=as.vector(axis_2),
z=axis_3,
type="scatter3d",
mode="markers",
name = "Obs",
marker = list(size = 3)) %>%
add_mesh(x=as.vector(axis_1),
y=as.vector(axis_2),
z=df_m2$pred,
type = "mesh3d",
name = "Preds")

Bug in a custom encryption/decryption program

I'm creating an encryption software in python 3.5. It should go along a key, using key[0] to shift raw[0], then key[1] to shift raw[1] etc, going back to key[0] when raw[i] is greater then key[i%len(key)].
# Converts the key into a numerical list.
def convert(alph, key):
for i in range(0, len(key)):
rem = alph.index(key[i])
numkey.append(rem)
print(numkey)
return numkey
#shifts the text dependant on the key
def encrypt (numkey, raw, alph):
encr = ""
emi = ()
emi = list(emi)
for i in range (0, len(raw)):
rem = raw[i]
rem = alph.index(rem)
suba = i%len(numkey)
ram = numkey[suba]
shift = (rem + ram) % 28 #ensures that shift is an index of alph
shift = alph[shift]
emi.append(shift)
for i in range(0, len(emi)):
encr = encr + str(emi[i])
print (encr)
letters = [
' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
'l', 'm', 'n', 'o', 'p', 'q', 'r', 't', 's', 'u', 'v', 'w',
'x', 'y', 'z', '.', ',', '!', '?']
raw_key = input("Please enter the key:\n")
raw_text = input("Please enter the text you would like to encrypt (no numbers or capitals):")
numkey = convert(letters, raw_key)
encrypt(numkey, raw_text, letters)
My problem is with the decryption program(below).
# Converts the key into a numerical list.
def convert(alph, key):
numkey = ()
numkey = list(numkey) # parse numkey as list
for i in range(0, len(key)):
rem = alph.index(key[i])
numkey.append(rem)
return numkey
# shifts the text dependant on the key
def encrypt (numkey,raw,alph):
encr = ""
emi = ()
emi = list(emi)
for i in range (0, len(raw)):
rem = raw[i]
rem = alph.index(rem)
suba = i%len(numkey)
ram = numkey[suba]
shift = (rem - ram)
if shift < 0:
shift = shift + 28
else:
pass
shift = alph[shift]
emi.append(shift)
for i in range(0, len(emi)):
encr = encr + str(emi[i])
print (encr)
letters = [
' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
'l', 'm', 'n', 'o', 'p', 'q', 'r', 't', 's', 'u', 'v', 'w',
'x', 'y', 'z', '.', ',' ,'!' ,'?']
raw_key = input("Please enter the key:\n")
raw_text = input("Please enter the text you would like to decrypt:\n")
numkey = convert(letters, raw_key)
encrypt(numkey, raw_text, letters)
For some reason, after encrypting the characters ",", "?" & "!", if I pass them beck through the decryption they always returns as " ", "a" and "b" respectively. This isn't a problem with any other element in the characters list.
If anyone can spot the problem I would be extremely grateful.
The problem is here in the encryption program:
shift = (rem + ram) % 28
The length of letters is 31 not 28. This is where you're looping back to the beginning of the array prematurely.
The problem is mirrored here in the decryption program:
shift = shift + 28
There are other problems as well. Just a few examples:
In the encryption program numkey is not initialized in convert()
no need to use range(), just use for char in key:
no need for the lst = () followed by lst = list(lst) pattern, just use a list in the first place, lst = []
no checking for invalid characters
function is still named encrypt() in the decryption program
Here's a quick first pass at cleaning both up.
Encryption:
import sys
LETTERS = (
' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
'l', 'm', 'n', 'o', 'p', 'q', 'r', 't', 's', 'u', 'v', 'w',
'x', 'y', 'z', '.', ',', '!', '?')
# Converts the key into a numerical list.
def convert(alph, key):
numkey = []
for char in key:
if char not in alph:
sys.exit("Invalid character")
numkey.append(alph.index(char))
print(numkey)
return numkey
# Shifts the text dependant on the key.
def encrypt (numkey, raw, alph):
encr = ""
for i, char in enumerate(raw):
if char not in alph:
sys.exit("Invalid character")
rem = alph.index(char)
ram = numkey[i % len(numkey)]
# Ensure that shift is an index of alph
shift = (rem + ram) % len(alph)
encr = encr + alph[shift]
print(encr)
raw_key = input("Please enter the key: ")
raw_text = input("Please enter the text you would like to encrypt (no numbers or capitals):\n")
numkey = convert(LETTERS, raw_key)
encrypt(numkey, raw_text, LETTERS)
Decryption:
import sys
LETTERS = (
' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
'l', 'm', 'n', 'o', 'p', 'q', 'r', 't', 's', 'u', 'v', 'w',
'x', 'y', 'z', '.', ',' ,'!' ,'?')
# Converts the key into a numerical list.
def convert(alph, key):
numkey = []
for char in key:
if char not in alph:
sys.exit("Invalid character")
numkey.append(alph.index(char))
return numkey
# Shifts the text dependant on the key.
def decrypt(numkey, raw, alph):
decr = ""
for i, char in enumerate(raw):
if char not in alph:
sys.exit("Invalid character")
rem = alph.index(char)
ram = numkey[i % len(numkey)]
shift = rem - ram
if shift < 0:
shift = shift + len(alph)
decr = decr + alph[shift]
print(decr)
raw_key = input("Please enter the key: ")
raw_text = input("Please enter the text you would like to decrypt:\n")
numkey = convert(LETTERS, raw_key)
decrypt(numkey, raw_text, LETTERS)

RColorBrewer Treemap package R, Change color for neutral value?

I would like to change the color of my boxes created in the treemap below. Like the code is written now all my boxes get colored green cause all values are higher than zero. How can I change the "neutral color value" in the palette so 100 represent the neutral value? In this case the boxes with a value smaller than 100 should go in the red color.
To just get the colors right I could take the value and subtract it by 100 but I also want my numbers to be correct.
Any and all help will be greatly appreciated.
Code:
library(treemap)
library(RColorBrewer)
name = c('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h')
weight = c(53796, 6897, 12928, 19838, 22745, 13456, 2333, 17567)
value = c(79, 87, 73, 109, 85, 76, 91, 104)
df = data.frame(name, weight, value)
treemap(df,
index="name",
vSize="weight",
vColor="value",
type="value",
palette = brewer.pal(n=8, "RdYlGn"))
Add mapping, e.g.:
treemap(df,
index="name",
vSize="weight",
vColor="value",
type="value",
palette = brewer.pal(n=8, "RdYlGn"),
mapping = c(min(value), 100, max(value)))

Drawing manually on a figure

I have generated a graph:
library(DiagrammeR)
grViz("
digraph boxes_and_circles {
# a 'graph' statement
graph [layout = neato, overlap = true, fontsize = 10, outputorder = edgesfirst]
# several 'node' statements
node [shape = circle,
fontname = Helvetica]
A [pos = '1,1!'];
B [pos = '0,2!'];
C [pos = '1.5,3!'];
D [pos = '2.5,1!'];
E [pos = '4,1!'];
F [pos = '4,2!'];
G [pos = '5,1!'];
H [pos = '6,2!'];
I [pos = '1.5,-0.1!'];
# several 'edge' statements
A->B B->C
D->E D->F E->F E->G F->G G->H F->H
}
")
Which produces:
Now I would like to draw a box with dotted lines around the nodes A, B, and C.
How can I accomplish this in R? A key requirement of the solution is that it is reproducible, i.e. that I can run the script multiple times and get the same result.
Here's another approach based on igraph. It is inspired by this igraph code sample.
I'm assuming that using igraph instead of DiagrammeR is an option - maybe that is not the case...
We leave positioning of the vertices to a standard layout algorithm and query it for the resulting vertex positions. These positions are then used to draw a dotted rectangle around an arbitrary set of "selected" vertices. No user interaction is needed.
We start with the graph topology.
library(igraph)
set.seed(42)
df <- data.frame(from = c('A', 'B', 'I', 'D', 'D', 'E', 'E', 'F', 'F', 'G'),
to = c('B', 'C', 'I', 'E', 'F', 'G', 'F', 'H', 'G', 'H'))
g <- graph.data.frame(df, directed = TRUE)
The size of the vertices and arrows in the graph can be set freely, according to taste.
vertexsize <- 50
arrowsize <- 0.2
We ask the Fruchterman-Reingold layout engine to calculate the coordinates of the vertices.
coords <- layout_with_fr(g)
Then plot the graph.
plot(g,
layout = coords,
vertex.size = vertexsize,
edge.arrow.size = arrowsize,
rescale = FALSE,
xlim = range(coords[,1]),
ylim = range(coords[,2]))
If we like to see what's going on, we can add coordinate axes and print the vertex coordinates:
axis(1)
axis(2)
V(g) # ordered vertex list
coords # coordinates of the vertices (in the same coordinate system as our dotted rectangle)
We now figure out the bounding box of the vertices that we want a rectangle around.
selectedVertices = c("A", "B", "C")
vertexIndices <- sapply(selectedVertices, FUN = function(x) { return(as.numeric(V(g)[x])) } )
llx <- min(coords[vertexIndices, 1])
lly <- min(coords[vertexIndices, 2])
urx <- max(coords[vertexIndices, 1])
ury <- max(coords[vertexIndices, 2])
Almost there. We already have the coordinates of the vertex centers in coords[], but we also need the size of the vertices in the coordinate system of plot(). From the plot.igraph source code we can see that the vertex.size option for plot() gets divided by 200 and then used as radius for drawing the vertex. We use a 50% bigger value as the margin around the bounding box of the vertex coordinates when drawing the dotted rectangle.
margin <- (vertexsize / 200) * 1.5
rect(llx - margin, lly - margin, urx + margin, ury + margin, lty = 'dotted')
This is the result we get:
You could use #StevenBeaupre's solution for the widget, but there are a few packages for graphing networks using R's graphics. One is igraph if you are open to using other solutions.
This will make the graph
library('igraph')
set.seed(11)
g <- data.frame(from = c('A', 'B', 'I', 'D', 'D', 'E', 'E', 'F', 'F', 'G'),
to = c('B', 'C', 'I', 'E', 'F', 'G', 'F', 'H', 'G', 'H'))
(gg <- graph.data.frame(g, directed = TRUE))
plot(gg, vertex.color = 'white')
And there are many ways to add a box to r graphics; here is one where you can click the plot to add the box without having to calculate anything
rekt <- function(...) {
coords <- c(unlist(locator(1)), unlist(locator(1)))
rect(coords[1], coords[2], coords[3], coords[4], ..., xpd = NA)
}
rekt(border = 'red', lty = 'dotted', lwd = 2)
I get this
An easy solution with DiagrammR would be to use dot rather than neato. You mostly lose the ability to manually position the nodes (attribute pos doesn't work anymore), but you gain the ability to use cluster and subgraph to draw lines around sets of nodes.
library(DiagrammeR)
grViz("
digraph boxes_and_circles {
# a 'graph' statement
graph [ fontsize = 10,rankdir=LR]
# several 'node' statements
node [shape = circle,
fontname = Helvetica]
# several 'edge' statements
subgraph cluster_1 {
style=dotted
A->B->C
}
D->E D->F E->F E->G F->G G->H F->H
I
}
")

Resources