问题
I would like to create a plot with categorical x values and lines and bars.
The example data is as follows:
dataWide <- iris %>%
group_by(Species) %>%
summarize(sl = mean(Sepal.Length),
sw = mean(Sepal.Width),
pl = mean(Petal.Length),
pw = mean(Petal.Width))
# Source: local data frame [3 x 5]
#
# Species sl sw pl pw
# 1 setosa 5.006 3.428 1.462 0.246
# 2 versicolor 5.936 2.770 4.260 1.326
# 3 virginica 6.588 2.974 5.552 2.026
I want to have:
- setosa, versicolor, and virginica on the x-axis. three lines
representing sl, sw, and pl, i.e.
layer_lines
withstroke = ~Species
- a
layer_bars
on a different scale, with axis label on the right.
I'm having trouble putting together the different functions together. Here's my failed attempt:
library(ggvis)
library(tidyr)
library(dplyr)
long <- dataWide %>%
select(Species, sl, sw, pl) %>%
gather(variable, value, sl : pl)
longPw <- dataWide %>% select(Species, pw) %>%
gather(variable, value, pw)
long %>%
ggvis(x = ~Species, y = ~value, stroke = ~variable) %>%
layer_lines() %>%
add_axis("y", "ypw", orient = "right", title = "PW", grid = F) %>%
layer_bars(x = ~Species, y = ~value, data = longPw, scale = "ypw")
回答1:
You can do it with the following code only, and as you will see there is a limitation which there is no solution for unfortunately:
First of all in order for this to work you need to use ONLY one dataset which will have all of the information you need. Then you use the following code:
Preparation of Data
dataWide <- iris %>%
group_by(Species) %>%
summarize(sl = mean(Sepal.Length),
sw = mean(Sepal.Width),
pl = mean(Petal.Length),
pw = mean(Petal.Width))
library(ggvis)
library(tidyr)
library(dplyr)
long <- dataWide %>%
select(Species, sl, sw, pl) %>%
gather(variable, value, sl : pl)
longPw <- dataWide %>% select(Species, pw) %>%
gather(variable, value, pw)
Have all the information you need for the plot in only one data set i.e. dataWide2:
dataWide2 <- cbind(dataWide, longPw[2:3])
Solution
dataWide2 %>%
#start with barchart
ggvis(x = ~Species, y = ~value) %>%
layer_bars(opacity := 0.4) %>%
#details for right axis i.e. the bars
add_axis("y", orient = "right", title = "My bars" ,title_offset = 50) %>%
#details for left axis i.e. the lines + plotting of lines
add_axis("y", 'ylines' , orient = "left", title= "My lines" , grid=F ) %>%
layer_lines(stroke := 'red', prop('y', ~sl, scale='ylines')) %>%
layer_lines(stroke := 'blue', prop('y', ~sw, scale='ylines')) %>%
layer_lines(stroke := 'green', prop('y', ~pl, scale='ylines'))
Few words for the above code:
- First of all you NEED to start with the barchart. I don't know why this happens but the opposite will produce an error.
- Secondly you need to create the lines separately since you are using one data set and set the colours individually.
Limitation
As you can see in the graph below the bar chart and the lines are not aligned which cannot be fixed so far unfortunately (at least to my current knowledge - check the Edit below). This limitation is actually the reason I made an account on stack overflow in the first place. If you check my profile this is my one and only question.
Hope it helps :)
EDITI don't know if this post is the reason for the bug report on ggvis on the github page but it was reported as a bug a few hours ago.
UPDATE
After a bit of researching and a bit of hacking I figured out a workaround which is as follows:
dataWide2 %>%
#start with barchart
ggvis(x = ~as.numeric(Species), y = ~value) %>%
layer_bars(opacity := 0.4) %>%
#add the initial x axis in order to set x labes to blank
add_axis('x', title='Species', properties = axis_props(labels=list(fill='blank'))) %>%
#details for right axis i.e. the bars
add_axis("y", orient = "right", title = "My bars" ,title_offset = 50) %>%
#details for left axis i.e. the lines + plotting of lines
add_axis("y", 'ylines' , orient = "left", title= "My lines" , grid=F ) %>%
layer_lines(stroke := 'red', prop('y', ~sl, scale='ylines')) %>%
layer_lines(stroke := 'blue', prop('y', ~sw, scale='ylines')) %>%
layer_lines(stroke := 'green', prop('y', ~pl, scale='ylines')) %>%
#add new axis which will be for our categorical x axis
add_axis('x', 'myx2', orient='bottom', title='') %>%
#add categorical data and make lines invisible (we only need the categories anyway)
layer_lines(prop("x", ~ Species, scale = "myx2"), stroke := 'blank')
The data set is exactly the same and essentially in order to have aligned bars and lines the bars need to have a numeric x axis. I therefore, created a second overlapping x axis which hosts the categorical data.
The output:
I suppose you could set the grid=F
and remove some of the ticks you don't want but this is as good as it can get. Hope it helps!
P.S. you can control the width of the bars with the width
argument in layer_bars
.
来源:https://stackoverflow.com/questions/28485588/ggvis-layer-bars-and-layer-lines-on-different-y-axis