Interactive plot in R (part scatterplot, part network) - r

I am trying to build an interactive plot. It has properties between a scatterplot and a network - I have a list of nodes and edges (network), but I also would like to constrain the nodes, sometimes on the x-axis sometimes on both x- and y- axis (scatterplot). Finally, I have a text label associated with each node that I would like to display (instead of a dot). I was able to create this using ggplot2.
However, some data sets are too large for this to work without the text labels from each node overlapping. Hence, I would now like to add an interactive feature so that the plot consists of dots representing each node, but that upon UI (such as hovering over a dot), the text label belonging to that dot will be revealed.
I would like to achieve this using R.
I tried animint (https://github.com/tdhock/animint) but it seems to mostly allow interaction between two plots, and here I would like to keep it all in one plot.
I also tried htmlwidgets (http://www.htmlwidgets.org/). I looked at two of their packages: I tried using metricsgraphics (mjs_plot), as it has a show_rollover_text option and mouseover option. However, this package does not allow combination of geoms, and so I could not have both dots (nodes) and lines (edges) represented. I also tried network3D package, but that seems to automatically position nodes so that they are distanced far away from each other, and does not seem to provide options to fix each node on a given x and y location.
I am just looking for advice on any other packages I should maybe consider to solve this problem and/or if I may be missing a feature from a package I already tried that could solve this problem. Thank you.

Maybe identify() will be useful for you. But it works only for base plotting system.
x <- rnorm(300)
y <- rnorm(300)
labs <- seq(300)
plot(x,y)
identify(x,y, labels = labs, plot=TRUE)
identify pic

Related

How to add node size as legend in Cytoscape 3?

From an R function (cnetplot) I've obtained the following image which does not look very nice.
Therefore, I extracted the data from the R object and wrote a script to create an equivalent network data file that is readable by Cytoscape. The following equivalent plot from Cytoscape looks much better but the problem is that I am not able to add legends based on node size in Cytoscape as the R function did. I tried with Legend Creator app in cytoscspe but couldn't do it.
The original data and R code to reproduce the plots can be found in the following link.
ftp://ftp.lrz.de/transfer/Data_For_Plot/StackOverflow/
I looked into this Mapping nodes sizes and adding legends in cytoscape network, but in that case questioner already was able to load the node sizes as legends in cytoscape and moreover, he/she used a python package.
Any suggestions will highly be appreciated
Here's a little R script that will generate a min/max node size legend. You'll need to set the first variable to the name of the Visual Style in your network. This one works with the sample session file, "Yeast Perturbation.cys" if you want to test it there first.
If you are familiar with RCy3, then it should be self-explanatory. You can customize the positioning of the nodes, labels and label font size, etc. You can even adapt it to generate intermediate values (like in your example above) if you want.
NOTE: This adds nodes to your network. If you run a layout after adding these, then they will be moved! If you rely on node counts or connectivity measures, then these will affect those counts! Etc.
If you find this uesful, I might try to add it as helper function in the RCy3 package. Let me know if you have feedback or questions.
# https://bioconductor.org/packages/release/bioc/html/RCy3.html
library(RCy3)
# Set your current style name
style.name <- "galFiltered Style"
# Extract min and max node size
res<-cyrestGET(paste0("styles/",style.name,"/mappings/NODE_SIZE"))
size.col <- res$mappingColumn
min.size <- res$points[[1]]$equal
min.value <- res$points[[1]]$value
max.size <- res$points[[length(res$points)]]$equal
max.value <- res$points[[length(res$points)]]$value
# Prepare as data.frame
legend.df <-data.frame(c(min.size, max.size), c(min.value, max.value))
colnames(legend.df) <- c("legend.label",size.col)
rownames(legend.df) <- c("legend.size.min", "legend.size.max")
# Add legend nodes and data
addCyNodes(c("legend.size.min", "legend.size.max"))
loadTableData(legend.df)
# Style and position
setNodeColorBypass(c("legend.size.min", "legend.size.max"),"#000000")
setNodePropertyBypass(c("legend.size.min", "legend.size.max"),
c("E,W,l,5,0", "E,W,l,5,0"), # node_anchor, label_anchor, justification, x-offset, y-offset
"NODE_LABEL_POSITION")
setNodeLabelBypass(c("legend.size.min", "legend.size.max"), legend.df$legend.label)
setNodePropertyBypass("legend.size.max",
as.numeric(max.size)/2 + as.numeric(min.size)/2 + 10, # vertical spacing
"NODE_Y_LOCATION")
setNodeFontSizeBypass(c("legend.size.min", "legend.size.max"), c(20,20))

Plotly Multi Column Horizontal Legend

I am trying to create horizontal bar chart in in R using the plotly package. Due to the length of the legend items I would like for them to show horizontally at the top or bottom of the visual in 2 columns. Is it possible to dictate the number of columns for the legend?
I've been able to place the legend below the x axis successfully using Layout(legend = list(orientation='h')) however regardless of where I put the legend (using the x and y arguments) it is always just one long list. I've seen a github project for creating a multi column legend in js but not r.
Thanks,
This is not possible in a normal way. I think it has its own logic that determines how many place there it is and how many columns it will display then.
So I guess if you make your plot width smaller you could reach the goal that it will just display 2 column.
Also you can try to play around with the margin attribute (https://plot.ly/r/reference/#layout-margin) by setting r and l to 10 e.g.
An other idea could be to make the font-size in legend (https://plot.ly/r/reference/#layout-legend-font-size) bigger, so that it just uses two columns. Hope it helps.
I read the same github page and I thought that it is not possible, but seems to be! I only checked in Python, but I hope this will help in your endeavors in R as well as everyone in Python looking for information. Sadly, there is not a lot of information on Plotly here compared to other packages.
This solved my problem
Setting orientation='h' is not enough. You also have to put the legend items in different legendgroups, if you want them in different columns. Here is an example with legend labels:
fig = go.Figure([
go.Scatter(x=best_neurons_df['Test Size'],
y=best_neurons_df['Training Accuracy Max'],
# You can write anything as the group name, as long as it's different.
legendgroup="group2",
name='Training',
mode='markers',
go.Scatter(x=best_neurons_df['Test Size'],
y=best_neurons_df['Validation Accuracy Max'],
# You can write anything as the group name, as long as it's different.
legendgroup="group1",
layout=dict(title='Best Model Dependency on Validation Split',
xaxis=dict(title='Validation Set proportion'),
yaxis=dict(title='Accuracy'),
margin=dict(b=100, t=100, l=0, r=0),
legend=dict(x=1, y=1.01,xanchor='right', yanchor='bottom',
title='',
orientation='h', # Remember this as well.
bordercolor='black',
borderwidth=1
))
Example image

cluster: :clusplot axis in wrong direction

I'm trying to plot the cluster obtained from fuzzy c-means clustering.
The plot should look like this.
code for the plot
plot(data$Longitude, data$Latitude, main="Fuzzy C-Means",col=data$Revised, pch=16, cex=.6,
xlab="Longitude",ylab="Latitude")
library(maps)
map("state", add=T)
However, when I tried to use clusplot the plot is displaying in opposite direction(both top and bottom and left and right) as below.
I wanna know if there's a way to reverse the plot to show in the order as the above picture.
Also, for the very dense area, it's hard to find the ellipse label. I wanna know if there's a way to show the label inside the ellipse instead of outside.
code for 2nd pic
library(cluster)
clusplot(cbind(Geocode$Longitude, Geocode$Latitude), cluster, color=TRUE,shade=TRUE,
labels=4, lines=0,col.p=cluster,
xlab="Longitude",ylab="Latitude",cex=1)
clusplot is a function that performs a lot of magic for you. In particular it projects the data set - which happens in a way you don't like, unfortunately. (Also note the scales - it centered and scaled the data, too)
clusplot.default: Creates a bivariate plot visualizing a partition (clustering) of the data. All observation are represented by points in the plot, using principal components or multidimensional scaling.
As far as I can tell, clusplot doesn't have map support, but you will want such a map I guess...
While maybe you can use the s.x.2d parameter to specify the exact projection (and this way disable automatic scaling), it probably is still difficult to add the map. Maybe look at the source of clusplot instead, and take only the parts you want?

Shaded graph/network plot?

I am trying to plot quite large and dense networks (dput here). All I end up with is a bunch of overlapping dots, which does not really give me a sense of the structure or density of the network:
library(sna)
plot(data, mode = "fruchtermanreingold")
However, I have seen plots which utilizes fading to visualize the degree to which points overlap, e.g.:
How can I implement this "fading" in a plot of a graph?
Here's one way:
library(sna)
library(network)
source("modifieddatafromgist.R")
plot.network(data,
vertex.col="#FF000020",
vertex.border="#FF000020",
edge.col="#FFFFFF")
First, I added a data <- to the gist so it could be sourced.
Second, you need to ensure the proper library calls so the object classes are assigned correctly and the proper plot function will be used.
Third, you should use the extra parameters for the fruchtermanreingold layout (which is the default one for plot.network) to expand the area and increase the # of iterations.
Fourth, you should do a set.seed before the plot so folks can reproduce the output example.
Fifth, I deliberately removed cruft so you can see the point overlap, but you can change the alpha for both edges & vertices (and you should change the edge width, too) to get the result you want.
There's a ton of help in ?plot.network to assist you in configuring these options.

How to avoid overplotting (for points) using base-graph?

I am in my way of finishing the graphs for a paper and decided (after a discussion on stats.stackoverflow), in order to transmit as much information as possible, to create the following graph that present both in the foreground the means and in the background the raw data:
However, one problem remains and that is overplotting. For example, the marked point looks like it reflects one data point, but in fact 5 data points exists with the same value at that place.
Therefore, I would like to know if there is a way to deal with overplotting in base graph using points as the function.
It would be ideal if e.g., the respective points get darker, or thicker or,...
Manually doing it is not an option (too many graphs and points like this). Furthermore, ggplot2 is also not what I want to learn to deal with this single problem (one reason is that I tend to like dual-axes what is not supprted in ggplot2).
Update: I wrote a function which automatically creates the above graphs and avoids overplotting by adding vertical or horizontal jitter (or both): check it out!
This function is now available as raw.means.plot and raw.means.plot2 in the plotrix package (on CRAN).
Standard approach is to add some noise to the data before plotting. R has a function jitter() which does exactly that. You could use it to add the necessary noise to the coordinates in your plot. eg:
X <- rep(1:10,10)
Z <- as.factor(sample(letters[1:10],100,replace=T))
plot(jitter(as.numeric(Z),factor=0.2),X,xaxt="n")
axis(1,at=1:10,labels=levels(Z))
Besides jittering, another good approach is alpha blending which you can obtain (on the graphics devices supporing it) as the fourth color parameter. I provided an example for 'overplotting' of two histograms in this SO question.
One additional idea for the general problem of showing the number of points is using a rug plot (rug function), this places small tick marks along the margin that can show how many points contribute (still use jittering or alpha blending for ties). This allows the actual points to show their true rather than jittered values, but the rug can then indicate which parts of the plot have more values.
For the example plot direct jittering or alpha blending is probably best, but in some other cases the rug plot can be useful.
You may also use sunflowerplot, while it would be hard to implement it here. I would use alpha-blending, as Dirk suggested.

Resources