R语言 如何在ggplot中将两个连续变量Map到框的高度和宽度?

zdwk9cvp  于 2023-05-20  发布在  其他
关注(0)|答案(1)|浏览(144)

我想创建一个包含两个连续变量(v1和v2)和一个分类变量(例如水平A、B、C、D)的图。该图应显示比例矩阵。分类变量应位于x轴上,每列应有两个方框(v1和v2),代表该类别内每个连续变量的比例(在A内,v1/(v1+v2),然后v2/(v1+v2))。列的宽度应表示该类别内的总数的比例(A的v1+v2除以所有v1和v2的总和)
它应该看起来像一个热图,但变量类型(v1或v2)Map到颜色和高度和宽度的方块Map如上所述。
使用堆叠条形图的方法效果很好,接近我想要的,但条形图之间有水平空间。由于我已经使用宽度美学来Map每个类别中的比例,因此无法消除此空间。

或者,我尝试使用geom_tile,但也遇到了同样的空间问题,并没有导致所有高度为1的条形图。

我找到的最接近的解决方案是:ggplot2 heatmap with tile height and width as aes()
然而,在那个例子中,他们在X轴和Y轴上都有一个分类变量,这与我的情况略有不同。
可复制的参考示例:

library(tidyverse)

cat <- c("A","B","C","D")
v1 <- c(1,3,6,2)
v2 <- c(3,3,10,1)
df <- data.frame(cat,v1,v2)

df <- df %>%
  group_by(cat) %>%
  mutate(sum.cat = sum(v1,v2)) %>%
  mutate(prop.v1 = v1/sum.cat) %>%
  ungroup() %>%
  mutate(prop.cat = sum.cat/sum(v1,v2)) %>%
  mutate(sum.tot = sum(sum.cat)) %>%
  mutate(prop.v2 = 1-prop.v1) %>%
  pivot_longer(cols = c(5,8), names_to = "prop.v.type", values_to = "prop.v")

ggplot(df,aes(cat,prop.v, fill = prop.v.type))+
  geom_bar(position = "stack", stat = "identity",aes(width=prop.cat))

ggplot(df,aes(x=cat, y=prop.v, fill = prop.v.type))+
  geom_tile(aes(width=prop.cat,height=prop.v))

先谢谢你了!

eqoofvh9

eqoofvh91#

这可以通过对x轴值进行一点修改来完成。我所做的是根据www.example.com计算x轴值prop.cat并将cat标签分配给与每个cat对应的每个条形位置的匹配值。这将使x轴连续值,以便width aes现在能够匹配轴值。

library(tidyverse)

cat <- c("A","B","C","D")
v1 <- c(1,3,6,2)
v2 <- c(3,3,10,1)
df <- data.frame(cat,v1,v2)

df <- df %>%
  group_by(cat) %>%
  mutate(sum.cat = sum(v1,v2)) %>%
  mutate(prop.v1 = v1/sum.cat) %>%
  ungroup() %>%
  mutate(prop.cat = sum.cat/sum(v1,v2)) %>%
  mutate(sum.tot = sum(sum.cat)) %>%
  mutate(prop.v2 = 1-prop.v1) %>%
  pivot_longer(cols = c(5,8), names_to = "prop.v.type", values_to = "prop.v")

# Here I calculate the x_axis position for each cat
df_revised <- df |> 
  group_by(cat) |>
  mutate(prop.cat_cumsum = if_else(row_number() == 1, prop.cat, 0)) |>
  ungroup() |>
  mutate(prop.cat_cumsum = cumsum(prop.cat_cumsum)) |>
  mutate(x_axis_value = 0 + prop.cat_cumsum - prop.cat / 2)

# As the cat & the values are well aligned in order so I just extract them
x_asix_breaks <- unique(df_revised$x_axis_value)
x_asix_labels <- unique(df_revised$cat)

# Now I plot them to test if it fit well.
ggplot(df_revised,
       aes(x = x_axis_value, y = prop.v, fill = prop.v.type))+
  geom_bar(position = "stack", stat = "identity",
           aes(width = prop.cat)) +
  scale_x_continuous(breaks = x_asix_breaks, expand = c(0, 0)) +
  scale_y_continuous(expand = c(0, 0))
#> Warning in geom_bar(position = "stack", stat = "identity", aes(width =
#> prop.cat)): Ignoring unknown aesthetics: width

好的,它和预期的一样工作。现在只需要分配适当的猫标签的x轴和添加一个线边界的酒吧,以便很容易区分酒吧。

ggplot(df_revised,
       aes(x = x_axis_value, y = prop.v, fill = prop.v.type))+
  geom_bar(position = "stack", stat = "identity",
           color = "black", aes(width = prop.cat)) +
  scale_x_continuous(breaks = x_asix_breaks, labels = x_asix_labels,
                     expand = c(0, 0)) +
  scale_y_continuous(expand = c(0, 0))
#> Warning in geom_bar(position = "stack", stat = "identity", color = "black", :
#> Ignoring unknown aesthetics: width

创建于2023-05-18带有reprex v2.0.2

相关问题