Change direction and rotation of a scatterpolar plot in R - r

I have a data set showing differences of two measurements of the same structure with two different methods as distance in meters and direction in degree. I found the scatterpolar plot of the function plot_ly of the package plotly in R, which produced almost what I wanted, but with some problems with the layout. Here is the code I used:
library(plotly)
data <- data.frame(measurements_compare); data
fig <- plot_ly(
type = 'scatterpolar',
r = c(data$distance),
theta = c(data$rotation),
text = c(data$id),
mode = 'markers',
)
fig
What I got from that was this plot, which is already quite close to what I want:
Now I would like to rotate the plot so that 0° is at the top instead of 90°, also I would like the degrees to be plotted ascending clockwise instead of counterclockwise. I found code examples for that in the archive where the function update_layoutwas used, but this example uses Python instead of R. I could not find something similar for R, but I am pretty sure there must be.

Inn plotly you can oftten use the same arguments in R and Python. For your code Rs layout function is needed instead of Pythons update_layout.
Example Data
data <- data.frame(distance = sample(seq(.1, .5, by = .01), 15, T),
rotation = sample(0:360, 15, T),
id = paste0(1:15))
Code
fig <- plot_ly(
type = 'scatterpolar',
r = c(data$distance),
theta = c(data$rotation),
text = c(data$id),
mode = 'markers',
) %>%
layout(polar = list(
angularaxis = list(
rotation = 90,
direction = "clockwise"
)
))
fig
Plot

Related

Smooth line with Plotly in R

I have one data set which contain data in two column about Gross salary and tax wedge.You can see data with code line below:
SAMPLE_WAGES_TAX_WEDGE_TEST<-data.frame(
GROSS=c(10,20,30,40,50,60,70,80,90,100,200,300,400,500,600,700,800,900,1000),
TAXWEDGE=c(30.1,30.4,30.7,30.9,29.1,28.9,28.6,28.5,27.9,27.2,27.1,27.0,27.0,26.8,25,24,23,21,19)
)
So my intention is to plot graph with plotly package and make some smooth line similar like function geom_smooth() from ggplot2.
library(data.table)
library(plotly)
dat <-as.data.table(SAMPLE_WAGES_TAX_WEDGE_TEST)
fig <- plot_ly(dat, x = ~GROSS, y = ~TAXWEDGE, name = "Before reform", type = 'scatter',
mode = 'lines',line = list(dash = "solid") )
I try with this line of code but I can't add smooth line so can anybody help how to solve this problem ?
There are two ways how to solve this issue:
1) Convert ggplot object into plotly
ggfig <- ggplot(dat, aes(x=GROSS, y=TAXWEDGE) ) +
geom_line() + geom_smooth()
ggplotly(ggfig)
2) geom_smooth() is based on the loess smoother. You need to fit the loess first and use it in add_ribbons in connection with plot_ly object. Check this great blog entry (the last example) for implementation guidance on loess and other smoothers.
Referring and complementing the answer in Adding a smoothed line to a plotly chart, you may directly use plotly with the shape = 'spline' option within the line marker specifications in order to get that type of smoothing (see e.g. https://en.wikipedia.org/wiki/Spline_interpolation):
plot_ly(SAMPLE_WAGES_TAX_WEDGE_TEST, x = ~GROSS, y = ~TAXWEDGE, type = 'scatter',
mode = 'lines', line = list(shape = 'spline', smoothing = 1.3))
where the optional parameter smoothing serves to (slightly) tune the degree of smoothing (see https://plotly.com/r/reference/scatter/#scatter-line-smoothing). Equivalently, using the specific add_lines trace function,
plot_ly(SAMPLE_WAGES_TAX_WEDGE_TEST, x = ~GROSS, y = ~TAXWEDGE) %>%
add_lines(line = list(shape = 'spline', smoothing = 1.3))

R Plotly rotation of text in add_text

I can't seem to get the text to rotate in Plotly, in a scatter plot, using add_text().
I'm just trying to get the same result that the angle argument yields in ggplot. In plotly, the output needs to have the hovertext if that's of consequence.
Example -
library(dplyr)
library(plotly)
data <- data.frame(
x = 1:10,
y = runif(10,0,10),
lab = LETTERS[1:10]
)
# base output needed in ggplot
p <- data %>%
ggplot(aes(x,y)) +
geom_text(aes(label = lab, angle = 90))
# doesn't respect angle arg - not that I'm looking to use ggplotly
ggplotly(p)
# plotly version
plot_ly(data) %>%
add_text(
x = ~x,
y = ~y,
text = ~lab,
hovertext = ~paste0("Label is ", lab),
# things I've tried (generally one at a time..)
textfont = list(angle = 90, textangle = 90, orientation = 90, rotate = 90)
)
I'm sure I'm missing something obvious, but I can't track it down.. Help pls!
It appears the solution is to use add_annotations() rather than add_text(). A textangle arg is then accpeted.
Edit - turns out you need two traces - annotations to achieve the text rotation, then markers for the hovertext. Setting opacity = 0 for the markers seems OK.

Plotly: Parallel Coordinates Plot: Axis Styling

I really like the parallel coordinates plot available in
Plotly but I just ran into an issue I could use help with.
Is it possible to have log10 based axis for some of the coordinates?
As you can see in the example below performing a log10 transform allows to better distinguish the smaller values. However, by transforming the data we loose the ability to interpret the values. I would prefer to log scale the axis instead of the data but couldn't find a way to do this.
I did find something related to "axis styling" in the github issue https://github.com/plotly/plotly.js/issues/1071#issuecomment-264860379 but
not a solution to this problem.
I would appreciate any ideas/pointer.
library(plotly)
# Setting up some data that span a wide range.
df <- read.csv("https://raw.githubusercontent.com/bcdunbar/datasets/master/iris.csv")
df$sepal_width[1] = 50
df$sepal_width_log10 = log10(df$sepal_width)
p <- df %>%
plot_ly(type = 'parcoords',
line = list(color = ~species_id,
colorscale = list(c(0,'red'),c(0.5,'green'),c(1,'blue'))),
dimensions = list(
list(range = c(~min(sepal_width),~max(sepal_width)),
label = 'Sepal Width', values = ~sepal_width),
list(range = c(~min(sepal_width_log10),~max(sepal_width_log10)),
tickformat='.2f',
label = 'log10(Sepal Width)', values = ~sepal_width_log10),
list(range = c(4,8),
constraintrange = c(5,6),
label = 'Sepal Length', values = ~sepal_length))
)
p
More Parallel Coordinate Examples
Plotly Parallel Coordinates Doc
Since the log projection is not supported (yet) creating tick labels manually seems to be a valid solution.
# Lets create the axis text manually and map the log10 transform
# back to the original scale.
my_tickvals = seq(min(df$sepal_width_log10), max(df$sepal_width_log10), length.out=8)
my_ticktext = signif(10 ^ my_tickvals, digits = 2)
library(plotly)
# Setting up some data that span a wide range.
df <- read.csv("https://raw.githubusercontent.com/bcdunbar/datasets/master/iris.csv")
df$sepal_width[1] = 50
df$sepal_width_log10 = log10(df$sepal_width)
# Lets create the axis text manually and map the log10 transform back to the original scale.
my_tickvals = seq(min(df$sepal_width_log10), max(df$sepal_width_log10), length.out=8)
my_ticktext = signif(10 ^ my_tickvals, digits = 2)
p <- df %>%
plot_ly(type = 'parcoords',
line = list(color = ~species_id,
colorscale = list(c(0,'red'),c(0.5,'green'),c(1,'blue'))),
dimensions = list(
list(range = c(~min(sepal_width),~max(sepal_width)),
label = 'Sepal Width', values = ~sepal_width),
list(range = c(~min(sepal_width_log10),~max(sepal_width_log10)),
tickformat='.2f',
label = 'log10(Sepal Width)', values = ~sepal_width_log10),
list(range = c(~min(sepal_width_log10),~max(sepal_width_log10)),
tickvals = my_tickvals,
ticktext = my_ticktext,
label = 'Sepal Width (log10 axis)', values = ~sepal_width_log10),
list(range = c(4,8),
constraintrange = c(5,6),
label = 'Sepal Length', values = ~sepal_length))
)
p
The underlying plotly.js parcoords doesn't support log projection (scales, axes) at the moment, though as you mention it comes up sometimes and we plan with this functionality. In the meantime, an option is to take the logarithm of the data ahead of time, with the big drawback that axis ticks will show log values, which needs explanation and adds to cognitive burden.

Defining outer edge of filled 2d Contour plot in plotly

Problem: I am trying to reproduce a round filled 2d contour plot in R using plotly (have tried ggplot2 also but plotly seemed to be easier).
Data: Sample data download link -
https://drive.google.com/file/d/10Mr5yWVReQckPI6TKLY_vzPT8zWiijKl/view?usp=sharing
The data to be plotted for contour is in a column format and typically called z variable, there is x and y data also available for all values of z. A simple dataframe would look like this:
Please ignore the repeat common x and y as I have truncated decimals. The data has about 25000 rows.
Approach: I first use akima package to interpolate z variable values for given x and y to map z in 2d. This makes the z column data fit in a xy grid for 2d plotting and show contours.
Expected outcome:
Code used:
dens <- akima::interp(x = dt$`Xvalue(mm)`,
y = dt$`Yvalue(mm)`,
z = dt$Values,
duplicate = "mean",
xo=seq(min(dt$`Xvalue(mm)`), max(dt$`Xvalue(mm)`), length = 10),
yo=seq(min(dt$`Yvalue(mm)`), max(dt$`Yvalue(mm)`), length = 10))
plot_ly(x = dens$x,
y = dens$y,
z = dens$z,
colors = c("blue","grey","red"),
type = "contour")
Actual outcome:
Help Needed:
To refine edges of the actual outcome plot to something of a close match to the expected outcome image.
Many thanks in advance for your comments and help.
I found that I could increase the grid output z matrix from akima::interp() from default 40x40 to custom using nx and ny input in function.
And then in plot_ly() add contours = list(coloring = 'fill', showlines = FALSE) to hide contour lines to get output close to my expected outcome.
So working code is like this:
dens <- akima::interp(x = dt$`Xvalue(mm)`,
y = dt$`Yvalue(mm)`,
z = dt$Values,
nx = 50,
ny = 50,
duplicate = "mean",
xo=seq(min(dt$`Xvalue(mm)`), max(dt$`Xvalue(mm)`), length = 50),
yo=seq(min(dt$`Yvalue(mm)`), max(dt$`Yvalue(mm)`), length = 50))
plot_ly(x = dens$x,
y = dens$y,
z = dens$z,
colors = c("blue","grey","red"),
type = "contour",
contours = list(coloring = 'fill', showlines = FALSE))
Plotly contour plot reference was very helpful in this case:
https://plot.ly/r/reference/#contour

Show observations that are outliers in plot_ly

I am plotting jitter boxplots through plotly in R. Plotly boxplots allow analyzing interactively the quartiles and the values of outliers. (Examples here: https://plot.ly/r/box-plots/)
I would like to see the name of observations that are outliers, so I can analyze them later.
However, it seems that boxplots don't have the option of watching to which observation they belong to, in contrast to scatter boxplots, where one can see it through 'text' option.
Before implementing other approaches, however, I would like to confirm that there is no possibility to have this information plotted.
I didn't find this option also.
I tried to plot but I didn't succeed, so I Located the outlier with the function boxplot.stats and wrote over it.
Look this example:
set.seed(1234)
a<-rnorm(50)
a2 <- rnorm(50, 1)
plot_ly(y = a, type = 'box') %>%
add_trace(y = a2) %>%
layout(title = 'Box Plot',xaxis = list(title = "cond", showgrid = F), yaxis = list(title = "rating"),
annotations = list(
x = -0.01,
y = boxplot.stats(a)$out,
text = "Outlier",
showarrow = FALSE,
xanchor = "right"
))
If you still want the outliers labeled by tooltips you can also identify them separately and pass the outliers dataset to add_marker(), overwriting the boxplot outliers. Try something like this:
#Set seed
set.seed(9)
#Generate random dataset
x <- data.frame(values = rnorm(100,sd=2),labels = paste("point",as.character(1:100)))
#Get outliarsdata
vals <- boxplot(x[,"values"],plot = FALSE)
#Make outliars dataset
y <- x[x[,"values"] > vals$stats[5,1] | x[,"values"] < vals$stats[1,1],]
#Make plot
plot_ly(x,y = ~values,x = 1,type = "box") %>%
add_markers(data = y, text = y[,'labels'])
I know that this comes horrendously late.
Check This link. Plotly allows a few options for showing outliers.
Curiously, it does not allow any option to NOT plot outliers (that is what I was looking for).

Resources