Related
I'm getting a Network Map done using R with visNetwork library, but I hate that displayed legend has text inside the shape, so it's size is defined by how big the name is and I don't want it to be that way to avoid confusion. In library documentation they add shapes that display text outside, but you have to set it group by group with a visGroups piece (shape = "triangle", for example) for each one of the groups and I want it set in a way where I can leave that code set without specifically knowing how many groups they will be, because it won't necesarilly be the same number every time.
Coding below is the one I'm using (way much bigger, made it simple by selecting only some colums & rows):
library(igraph)
library(visNetwork)
twd2 <- structure(c(0.0854374047081175, 0.116200039661793, 0.0289142580616779,
0.12768720590989, 0.273786051264039, 0, 0.000593902599973604,
0, 0.00184397276348455, 0, 0, 0, 0, 0, 0, 0, 0.106048390315551,
0, 0, 0, 0.0142648455772593, 0, 0.0197857551361577, 0.0290239379534046,
0, 0, 0, 0, 0, 0, 0, 0, 0.00197967638677129, 0, 0.000296951299986802,
0, 0.0111915576381184, 0, 0.00111081782587656, 0.0276104933163398,
0, 0, 0.00487220095904272, 0.0149921777316026, 0, 0, 8.79855703664599e-05,
0.00674104365369398, 0, 0, 0.0330935726540847, 0, 0, 0.0362094142674287,
0, 0, 0, 0.00172168238114983, 0.00232061941841538, 0.0248983709144504
), .Dim = c(4L, 15L), .Dimnames = list(NULL, c("water_treatment",
"waste_water", "utility_model", "water_inlet", "waste_water_treatment",
"treatment_system", "model_discloses", "utility_model_discloses",
"water_outlet", "water_treatment_system", "treatment_device",
"water_tank", "sludge_treatment", "reverse_osmosis", "raw_water")))
twd2_num_col <- ncol(twd2)
twd2_cor <- cor(twd2, method = "pearson")
twd2_cor[ abs(twd2_cor) < 0.75 ] <- 0
twd2_cor[ abs(twd2_cor) > 0.925 ] <- 0
diag(twd2_cor) <- 0
graph <- graph.adjacency(twd2_cor, weighted=TRUE, mode="lower")
E(graph)$edge.width <- E(graph)$weight
V(graph)$group <- apply(twd2, 2, which.max) # Max topic prob for colors
V(graph)$betweenness <- betweenness(graph, v = V(graph), directed = F)
V(graph)$degree <- degree(graph, v = V(graph))
# Fit data for visNetwork
nm_data <<- toVisNetworkData(graph)
nodes <<- as.data.frame(nm_data[[1]], stringsAsFactors = F)
nodes <<- nodes[nodes$degree != 0,] # Bye topics that don't have a connection (degree = 0)
nodes$group <<- swap(nodes$group , 1:length(topic_names), topic_names) # Swap long real names
nodes$label <<- rep("")
# Plot
# Graph
set.seed(17);visNetwork(as.data.frame(nodes, stringsAsFactors = F),
as.data.frame(nm_data[[2]], stringsAsFactors = F),
main = "Relation between topics") %>%
visOptions(highlightNearest = TRUE, selectedBy = "group") %>%
visInteraction(dragNodes = FALSE) %>%
visLegend(useGroups = TRUE, main = "Topic") %>%
visNodes(shape = "dot",label = NULL) %>%
visIgraphLayout(randomSeed = 17)
Additionaly, here they make reference to what I said aboud selecting type of shapes, but they don't add any code and I can't figure out if there is a way to do it directly and apply it to all group options or any other choice I could have.
ledges <- data.frame(color = c("lightblue", "red"),
label = c("reverse", "depends"), arrows =c("to", "from"),
font.align = "top")
visNetwork(nodes, edges) %>%
visGroups(groupname = "A", color = "red") %>%
visGroups(groupname = "B", color = "lightblue") %>%
visLegend(addNodes = lnodes, addEdges = ledges, useGroups = FALSE)
font.align = "top" must do the job
For future visitors;
See https://www.rdocumentation.org/packages/visNetwork/versions/2.0.9/topics/visNodes
The location of the label depends on the chosen shape, for default elipse this will be inside the node." The types with the label inside of it are: ellipse, circle, database, box, text. The ones with the label outside of it are: image, circularImage, diamond, dot, star, triangle, triangleDown, square and icon."
When I want to export a wordcloud2 picture, the wordcloud seems to be recalculated and looks very different from the one in the viewer.
How can I prevent R from creating another picture?
library(wordcloud2)
wordcloud2(demoFreq[demoFreq$freq>7,],minRotation = 0, maxRotation = 0)
Pictures: https://drive.switch.ch/index.php/s/8WIkGEM88wd4UXc
Adding shuffle = FALSE keeps the words in place.
Defining nonrandom colors fixes the colors. Maybe with a color vector.
library(wordcloud2)
minfreq=10
upperpart= demoFreq[demoFreq$freq>minfreq,]
colorvector = rep(c('red','skyblue'), length.out=nrow(upperpart))
wordcloud2(demoFreq[demoFreq$freq>minfreq,],minRotation = 0,
maxRotation = 0,shuffle=FALSE, color=colorvector)
you should just add shuffle = FALSE in your function and in case you want to control the colors you can create a color palette using the rainbowfunction with the number of rows of your data input:
dataInput <- demoFreq[demoFreq$freq>7,]
my_colors <- rainbow(nrow(dataInput), start = 0.1) # check ?rainbow for more infos
wordcloud2(dataInput, minRotation = 0, maxRotation = 0, shuffle = F, color = my_colors)
gives you:
Hope this helps!
Creating 3D plots in R opens up an interactive window where the user can rotate the view. For example below using package rgl:
library(rgl)
plot3d(iris[,1:3],col=c("red","green","blue")[iris$Species],size=5)
Is there some way to set a predefined view and export the plot as a regular image. I would like to do this in an automated non-interactive manner for many datasets.
Use scatterplot3d package.
library(scatterplot3d)
graphics.off()
png(filename = "test.png", width = 8, height = 6, units = "in", res = 300)
par(mai = c(0.5, 0.5, 0.5, 0.5))
scatterplot3d(x = iris$Sepal.Length, y = iris$Sepal.Width, z = iris$Petal.Length,
color = c("red","green","blue")[iris$Species],
cex.symbols = 1, pch = 19, angle = -30)
dev.off()
Besides #d.b's answer using scatterplot3d instead of rgl, you could save results using R Markdown. The advantage of doing it this way is that you get an interactive display instead of a static one; the disadvantage is that the format is HTML, not PNG or another bitmap format.
Before knitting the document, run code like this and interactively choose
the initial display you want:
library(rgl)
options(rgl.useNULL = FALSE)
plot3d(iris[,1:3],col=c("red","green","blue")[iris$Species],size=5)
Once you have it oriented correctly, run this code:
M <- par3d("userMatrix")
dput(M)
You'll get something like
structure(c(0.776694416999817, 0.198224693536758, -0.597873568534851,
0, -0.629868388175964, 0.249577552080154, -0.735511302947998,
0, 0.00341932475566864, 0.947849154472351, 0.318700969219208,
0, 0, 0, 0, 1), .Dim = c(4L, 4L))
as output. Then start your R Markdown document with something like
library(rgl)
options(rgl.useNULL = TRUE)
M <- structure(c(0.776694416999817, 0.198224693536758, -0.597873568534851,
0, -0.629868388175964, 0.249577552080154, -0.735511302947998,
0, 0.00341932475566864, 0.947849154472351, 0.318700969219208,
0, 0, 0, 0, 1), .Dim = c(4L, 4L))
(which you would probably choose not to echo), and in each code chunk that produces a plot, write code like this:
plot3d(iris[,1:3],col=c("red","green","blue")[iris$Species],size=5)
par3d(userMatrix = M)
rglwidget()
(If this is in a loop or isn't at the top level for some other reason, you'll need print(rglwidget()) instead.)
Then all of your plots will initially have the same orientation, but all of them will be user-rotatable.
I am trying to plot a 3D graph in lattice using wireframe. I want to reset the margins between the 3d plot and the R window,
The top margins is too big and this wastes lots of space when I convert it into postscript files. I am trying to reduce to margins.
I tried the following R code par(mar=c(4,3,3,1)+0.1).
However nothing is happening.
Try this snippet, adapted from https://stat.ethz.ch/pipermail/r-help/2007-January/123556.html. It worked for me.
library(lattice)
theme.novpadding <- list(
layout.heights = list(
top.padding = 0,
main.key.padding = 0,
key.axis.padding = 0,
axis.xlab.padding = 0,
xlab.key.padding = 0,
key.sub.padding = 0,
bottom.padding = 0
),
layout.widths = list(
left.padding = 0,
key.ylab.padding = 0,
ylab.axis.padding = 0,
axis.key.padding = 0,
right.padding = 0
)
)
wireframe(volcano, shade = TRUE,
aspect = c(61/87, 0.4),
#par.settings = theme.novpadding, # uncomment this
light.source = c(10,0,10))
I want to plot three plots vary close together, so they appear as one field. My data are arrays with different dimensions.
Here is some example code to display my problem:
library(lattice)
theme.novpadding = list(layout.heights = list(top.padding = 0,
main.key.padding = 0,
key.axis.padding = 0,
axis.xlab.padding = 0,
xlab.key.padding = 0,
key.sub.padding = 0,
bottom.padding = 0),
layout.widths = list(left.padding = 0,
key.ylab.padding = 0,
ylab.axis.padding = 0,
axis.key.padding = 0,
right.padding = 0),
axis.line = list(col = "transparent"))
p1 = levelplot(array(c(1:100), c(10,10)), colorkey=F, par.settings=theme.novpadding)
p2 = levelplot(array(c(1:100), c(9,9)), colorkey=F, ylab = NULL, par.settings=theme.novpadding)
p3 = levelplot(array(c(1:100), c(11,11)), ylab=NULL, par.settings=theme.novpadding)
width = 0.33
height = 1
ph = list(5, "in")
print(p1, position = c(0, 0, width, height), panel.height=ph, more=T)
print(p2, position = c(width, 0, 2*width, height), panel.height=ph, more=T)
print(p3, position = c(2*width, 0, 3*width, height),panel.height=ph, more=F)
As you see, they are spread very wide. I want them as close as possible.
I use theme.novpadding to set the margins to zero.
Is the a way to say something like "distance between plots"?
This problem is easy to solve if you structure your data into a nice data.frame. Lattice works best on data.frames. See the example bellow:
g.xy <- expand.grid(1:10, 1:10)
my.data <- data.frame(x=g.xy$Var1, y = g.xy$Var2, value1=1:100, value2 = 1:100, value3=1:100, value4=1:100)
levelplot(value1+value2+value3+value4~x+y, data=my.data, scales=list(x="free", y="free")) # free
levelplot(value1+value2+value3+value4~x+y, data=my.data, scales=list(x="same", y="same")) # same range, so panels are "touching"
You can control for the plots to appear very close together by setting the scale argument.
A trick you could use is to tweak the position argument. In stead of not letting the areas overlap, you can do just that to make them close together. For example, you can change the position arguments to:
ovr = 0.05
print(p1, position = c(0, 0, width + ovr, height), panel.height=ph, more=T)
print(p2, position = c(width - ovr, 0, 2*width+ovr, height), panel.height=ph, more=T)
print(p3, position = c(2*width - ovr, 0, 3*width, height),panel.height=ph, more=F)
You have to some tweaking with this, and I have not tested this code. But I think the general idea should work.