log scale and limits with ggvis - r

Hi I'm a little confused with the scales in ggvis.
I'm trying to do two things: one is have a log scale (the equivalent of log="x" in plot()). I'm also looking for the equivalent of xlim=c(). In both cases, the code below is not giving the expected results.
# install.packages("ggvis", dependencies = TRUE)
library(ggvis)
df <- data.frame(a=c(1, 2, 3, 1000, 10000), b=c(0.1069, 0.0278, 0.0860, 15.5640, 30.1745))
df %>% ggvis(~a, ~b)
df %>% ggvis(~a, ~b) %>% scale_numeric("x", trans="log")
Notice that with trans="log", all dots are on the left of the plot and the scale disappears.
Next, I want to restrict the plot to certain values. I could subset the data frame but I'm looking to have the equivalent of xlim from plot().
df %>% ggvis(~a, ~b) %>% scale_numeric("x", trans="linear", domain=c(10, 40))
This is giving even weirder results, so I'm guessing I might be misinterpreting what domain does.
Thanks for your help!

I've encountered the same problem that you've mentioned.
Apparently, the developer of ggvis noticed this bug as well. This is currently marked as an issue. You can find the issue here: https://github.com/rstudio/ggvis/issues/230
In the context of your question:
# install.packages("ggvis", dependencies = TRUE)
library(ggvis)
df <- data.frame(a=c(1, 2, 3, 1000, 10000), b=c(0.1069, 0.0278, 0.0860, 15.5640, 30.1745))
df %>% ggvis(~a, ~b)
# Points will disapper
df %>% ggvis(~a, ~b) %>% scale_numeric("x", trans="log")
# Should work
df %>% ggvis(~a, ~b) %>% scale_numeric("x", trans="log", expand=0)
However, you may notice that after the transformation, the spacing between ticks don't appear to be uniform. But at least the dots are rendered correctly.

I ran into the same issue and noticed that as soon as I removed the 0 data points from my data (of which log() cannot be computed) everything started to work fine.

This is strange, I've now tried a lot of things with your data, but can't find the problem.
The I tested it on the Violent Crime Rates by US State (see help(USArrests)) and it worked like a charm.
data(USArrests)
# str(USArrests)
p <- USArrests %>% ggvis(~ Murder, ~ Rape) %>% layer_points()
p %>% scale_numeric("y", trans = "log")
This is not an answer, simply to share this with you.

Related

Using tidygraph to derive nodes and graph-level metrics per group

I am trying out tidygraph on networks coming from different experimental treatments and am mostly interested to get out graph-wide metrics and potentially also node-level metrics. I can't seem to be able to get my head around the way tidygraph works.
I am using R v3.5 and tidygraph v1.1.
My data are structured in that way:
dat <- data.frame(Treatment = rep(c("A","B"),each = 2),
from = c("sp1","sp2","sp1","sp2"),
to = c("sp2","sp3","sp3","sp3"),
weight = runif(4))
If I want to get per treatment a graph-wide metric like the diameter I would be tempted to do:
dat %>%
as_tbl_graph() %>%
activate(edges) %>%
group_by(Treatment) %>%
mutate(Diameter = graph_diameter(weights = weight))
But I am unsure about the result as the diameters are then given for each edges while I would be expecting one measure per treatment (per graph).
Similarly if I want to derive some metrics like the connectivity of each node for each treatment this appears to be not so straightforward since the treatment variables is dropped from the nodes table. I have been trying various hacks like pasting the treatment IDs to the from and to columns before calling as_tbl_graph() along these lines:
dat %>%
mutate(from = paste(from, Treatment, sep = "_"),
to = paste(to, Treatment, sep = "_")) %>%
as_tbl_graph() %>%
mutate(Treatment = substr(name, 5, 5), name = substr(name, 1, 3)) %>%
group_by(Treatment) %>%
mutate(Centrality = centrality_betweenness())
But I got errors that the resulting vectors were of the wrong size (6 instead of 3 or 1).
Is there a way with tidygraph to derive group-level graph-wide and node-level metrics?
I think that this is an interesting problem. I have tried several times and still haven't got the best solution for it. But, I suspect that this problem needs morph() function in order to separate graph properly. Again, I haven't explore that much. But, here I give the simple solution for the diameter problem using morph() function. Hope it helps you.
dat %>%
as_tbl_graph() %>%
activate(edges) %>%
morph(to_split,split_by = "edges")%>%
filter(Treatment=="A") %>%
mutate(Diameter = graph_diameter(weights = weight)) %>%
unmorph() %>% activate(edges) %>%
morph(to_split,split_by = "edges") %>%
filter(Treatment=="B") %>%
mutate(Diameter = graph_diameter(weights = weight)) %>%
unmorph()

Altering Linewidth and Color for LineString Objects in Mapview

I'm working with reefs across a large area and trying to visualize them quickly such that I can pick a smaller subset to work on initially. To do this, I have taken my spatial points, transformed them to LineString to make the mapping quicker and then used mapview to display them. The code I have is below:
data_as_sf %>%
filter(reef_name %in% subgroup) %>%
group_by(.dots=c("reef_name", "reef_section")) %>%
summarize() %>%
st_cast("LINESTRING") %>%
mapview()
A zoomed in sample of the mapview generated is here:
If anyone can provide advice such that I can
make the lines bigger/thicker so they are more easily seen when
zoomed out, and
have the lines colored by the factor "reef_name"
it would really help.
As answered in the comments by TimSalabim, have now updated the code to be
data_as_sf %>%
filter(reef_name %in% subgroup) %>%
group_by(.dots=c("reef_name", "reef_section")) %>%
summarize() %>%
st_cast("LINESTRING") %>%
mapview(lwd = 3, zcol = "reef_name")
which works just right.

ggvis barplot: negative values

I'm trying to draw a barplot using ggvis, for some data where for each variable I have both a negative and a positive value. It would be similar to this example from ggplot2.
However, when I try something similar in ggvis, I end up with basically no plot at all, just some weird lines.
Example data:
df <- data.frame(
direction=rep(c("up", "down"), each=3),
value=c(1:3, -c(1:3)),
x=rep(c("A", "B", "C"), 2))
This works, for all positive values:
df %>%
mutate(value.pos=abs(value)) %>%
ggvis(x=~x, y=~value.pos) %>%
group_by(direction) %>%
layer_bars(stack=TRUE)
This gives me nothing:
df %>%
ggvis(x=~x, y=~value) %>%
group_by(direction) %>%
layer_bars(stack=TRUE)
I've also tried various combinations of plotting them one by one, e.g.:
df %>%
spread(key=direction, value=value) %>%
ggvis(x=~x, y=~up) %>%
layer_bars() %>%
layer_bars(x=~x, y=~down)
So far, no luck. I suspect I'm missing some simple solution...
I don't ggvis lets you produce stacked bar plots with negative values within the same groups as positive data.
This is because if an x value appear more than once in the data, then ggvis will sum up the y values at each x. I had thought that since you plotted the vector 1:3, they canceled out, but that's not the case.
As of now, I do not believe that dodged bar plots exist for this. It also messes with the labels.
You can produce the plot non-stacked, while filling in the position.
df %>%
group_by(direction) %>%
ggvis(x=~x, y=~value, fill = ~direction) %>%
layer_bars(stack = FALSE)
Anyways, you might consider avoiding ggvis for any production work since it is under development, and hasn't been updated in a couple of months.
#shayaa
Thanks, this does seem to be working, although it will probably require some tweaking, and may not look as nicely as if I was using ggplot2. Actually, the reason I am using ggvis, is because I would like to combine it with shiny, to make a small interactive web version. For example:
df <- data.frame(
direction=rep(c("up", "down"), each=3),
value=c(1:3, -c(1:3)),
x=rep(c("A", "B", "C"), 2))
plot_fct <- function(letter) {
df %>%
filter(x==letter) %>%
ggvis(x=~x, y=~value, fill = ~direction) %>%
layer_bars(stack = FALSE) %>%
scale_numeric("y", domain=c(NA,NA))
}
ui <- fluidPage(
sidebarPanel(
selectInput("letter", "Choose letter", c("A", "B", "C"), selected="A")
),
mainPanel(
ggvisOutput("letter_barplot")
)
)
server <- function(input, output) {
plot_fct(letter=reactive(input$letter)) %>% bind_shiny("letter_barplot")
}
runApp(shinyApp(ui, server))
However, it does not seem to work for me anyway, since there is some issue with the reactive being of class character. I keep getting the error:
Error in eval(substitute(expr), envir, enclos) :
comparison (1) is possible only for atomic and list types
Guess I'll have to keep trying.

Lines stroke (color) as legend and moving legend labels next to lines

I'm trying to use ggvis to make a plot similar to this one
and I'm running into two issues.
First, I've tried assigning the line stroke color as the legend shape but ggvis always keeps the circles. In addition, it doesn't recognize the dashed lines either.
library(ggvis)
data <-data.frame(region=rep(c("A","B","C"),5),c=rep(seq(1980,2000,5),3), val=rnorm(15))
data %>%
group_by(region) %>%
ggvis(~c, ~val) %>%
layer_smooths(stroke=~region, strokeDash = ~region,strokeWidth := 3, strokeOpacity := 0.65) %>%
add_axis("y", title="y") %>%
add_axis("x", title="y", format=####) %>%
add_legend(c("stroke","strokeDash")) ## Adding this does not update the legend to recognize the line color or dashes.
Some asked something here but no one answered.
Finally, I'd like to place the legend names of each region next to the lines just as in the first graph. For this, I haven't found out how to even start.
Any help is appreciated.
UPDATE:
I asked how to have x axis labels as numeric and the answer was adding format = "####" to add_axis.
I didn't manage to find what I needed specifically, but I found a partial solution. See the comments in the code.
data <-data.frame(region=rep(c("A","B","C"),5),c=rep(seq(1980,2000,5),3), val=rnorm(15))
data$region2 <- data$region ## create an additional region variable
data$region2 <- as.character(data$region2)
data$region2[data$c != 2000] <- "" ## Fill every year which is not the last year to be an empty character vector
data %>%
group_by(region) %>%
ggvis(~c, ~val) %>%
layer_smooths(stroke=~region, strokeDash = ~region,strokeWidth := 3, strokeOpacity := 0.65) %>%
layer_text(text := ~region2) %>% ## add this new region variable, which will only write over the last year.
add_axis("y", title="y") %>%
add_axis("x", title="y", format="####") %>%
hide_legend(c("stroke","strokeDash"))

How to add tooltip with shares to ggvis histogram?

I would like to create an interactive histogram which gives information about the bins by hover. This thread gives answer to how to add tooltip with count numbers.
library("ggvis")
cocaine %>%
ggvis(x = ~weight) %>%
layer_histograms() %>%
add_tooltip(function(df) (paste("count:", df$stack_upr_ - df$stack_lwr_)))
How can I add the share of each bin as well? I should somehow add nrow(cocaine) to ggvis and create the shares from count but I did not succeed on how to achieve that (tried to take the suggestions of this post but apparently that solves a different problem).
You could do something like this I imagine:
cocaine %>%
ggvis(x = ~weight) %>%
layer_histograms() %>%
add_tooltip(function(df) paste("count:", df$stack_upr_, 'share:',
format(df$stack_upr_/nrow(cocaine), digits=2)))
This will show both the share and the bin number.
Also, as a side note you do not need df$stack_upr_ - df$stack_lwr_ because df$stack_lwr_ will be zero. Just df$stack_upr_ will do.

Resources