我希望这个例子很清楚。我想在中间的横杠跨度为'0'的地方放置堆叠的横杠,因为它代表一个中性值。这与李克特量表一起使用。为了重现性,请使用Diamonds数据集。
下面的示例非常接近我的用例,并演示了我很难使“好”或“正”数据以正确的顺序排列(以使中性点最接近0)。
这是我的代码:
require(tidyverse)
diamonds_new <- diamonds %>%
mutate(quality = fct_recode(cut, "Very poor" = "Fair", "Poor" = "Good", "Neutral" = "Very Good", "Good" = "Premium", "Excellent" = "Ideal")) %>%
select(color, clarity, quality) %>%
group_by(color, clarity, quality) %>% count()
diamonds_bad <-
diamonds_new %>% filter(quality %in% c("Very poor", "Poor", "Neutral")) %>%
mutate(n = ifelse(quality == "Neutral", -n/2, -n))
diamonds_good <-
diamonds_new %>% filter(quality %in% c("Neutral", "Good", "Excellent")) %>%
mutate(n = ifelse(quality == "Neutral", n/2, n)) # %>%
# arrange(color, clarity, desc(quality)) # this doesn't seem to make a difference
ggplot() + geom_col(data = diamonds_bad, aes(x=color, y = n, fill = quality)) +
geom_col(data = diamonds_good, aes(x=color, y = n, fill = quality)) +
facet_grid(. ~ clarity, scales = "free") +
coord_flip()
我也尝试使用scale_fill_manual()
,但也没有找到一种可行的方法。
我认为,这比没有负值复杂性或不需要span 0
的现有示例更为复杂。使用当前版本的ggplot,我缺少什么?
此外,我是否正确,需要对正集合和负集合进行拆分,或者至少更容易做到这一点?
答案 0 :(得分:1)
由geom_col
创建的列是使用position_stack
形成的,该列分别堆叠正值和负值,其中正值向上堆叠而负值向下堆叠。通过将中心组Neutral
设置为等于其原始值的一半,然后将其绘制为正值和负值,可以使其跨度为0。另外,对于正值,组的顺序将需要颠倒。
这种方法有助于呈现我正在使用的某些调查的结果,因此我将其变成一个功能,使其更通用。
library(tidyverse)
#
# summarize groups and save counts in variable quality_cnt
#
diamonds_cnt <- diamonds %>%
mutate(quality = fct_recode(cut, "Very_Poor" = "Fair", "Poor" = "Good",
"Neutral" = "Very Good", "Good" = "Premium", "Excellent" = "Ideal")) %>%
select(color, clarity, quality) %>%
group_by(color, clarity, quality) %>% summarize(quality_cnt = n())
# make function to plot counts
plot_ratings <- function(survey, rated_item, rating_cnt, rating, rating_cat, facet = "wrap") {
#
# Input:
# rated_item = unquoted variable name of rated items
# rating = unquoted variable name of ratings for each rated_items;
# variable should be a factor ordered from lowest to highest
# rating_cnt = unquoted variable name of counts or frequencies for each rated_item
# rated_cat = unquoted variable name of categories of rated items
# facet = "grid" for all panels on one row or
# "wrap" to spread panels across multiple rows
#
# make arguments quosures
#
rated_item <- enquo(rated_item)
rating_cnt <- enquo(rating_cnt)
rating <- enquo(rating)
rating_cat <- enquo(rating_cat)
#
# If number of rating levels is odd, find middle rating
#
rating_levels <- levels(pull(survey, !!rating))
mid_level <- ceiling(length(rating_levels)/2)
mid_rating <- ifelse(length(rating_levels)%%2 == 1, rating_levels[mid_level], NA_character_)
#
# make local variabels for use with aes
# plot positive and negative columns separately
#
survey <- survey %>% mutate( rating_plt = !!rating, rating_cnt_plt = !!rating_cnt)
sp <- ggplot(survey, aes_(x = rated_item, fill = rating)) +
geom_col(data=filter(survey, !!rating %in% tail(rating_levels, mid_level)),
aes( y = ifelse(rating_plt == mid_rating, .5*rating_cnt_plt, rating_cnt_plt)),
position = position_stack(reverse = TRUE )) +
geom_col(data=filter(survey, !!rating %in% head(rating_levels, mid_level)),
aes( y = ifelse(rating_plt == mid_rating, -.5*rating_cnt_plt, -rating_cnt_plt)),
position = "stack") +
labs(y = rating_cnt) +
scale_fill_brewer(palette = "RdYlGn", direction = -1) +
coord_flip() +
switch(facet,
grid = facet_grid( facets=rating_cat, scales = "free_x"),
wrap = facet_wrap( facets=rating_cat, scales = "free_x"))
plot(sp)
}
#
# Use function to make charts
#
plot_ratings(diamonds_cnt, rated_item = color, rating_cnt = quality_cnt,
rating = quality, rating_cat = clarity, facet = "wrap")
显示图表
答案 1 :(得分:0)
这样的事情-我的主要更改是从geom_col
转到geom_rectangle
,在这里您可以自由地控制开始和结束。
diamonds_new <- diamonds %>%
mutate(quality = fct_recode(cut, "Very poor" = "Fair", "Poor" = "Good", "Neutral" = "Very Good", "Good" = "Premium", "Excellent" = "Ideal")) %>%
select(color, clarity, quality) %>%
group_by(color, clarity, quality) %>%
count() %>%
group_by(color, clarity) %>%
arrange(quality) %>%
mutate(end = cumsum(n)) %>%
mutate(start = end-n) %>%
mutate(offset = (end[quality=="Neutral"] + start[quality=="Neutral"])/2) %>%
mutate(start = start - offset,
end = end - offset) %>%
mutate(colStart = as.numeric(color) + 0.25,
colEnd = as.numeric(color) + 0.75)
看到了第二个答案(并且没有看到OP的任何输入),我还提供了另一种选择。
ggplot() +
geom_rect(data = diamonds_new, aes(xmin=colStart, xmax=colEnd, ymin=start, ymax=end, fill = quality)) +
facet_wrap(. ~ clarity, scales="free_x") +
coord_flip()
WaltS的答案在y轴上保留了因子水平,这肯定更接近于原始问题。但是,这需要大量更改数据,因此我认为保留我的替代答案很有用。
如果零需要在面板中居中,则需要相应地调整xlim
。