问题描述
我正在尝试为 OD 矩阵创建热图,但我想按特定权重缩放行和列。由于这些权重在每个类别中都是恒定的,我希望该图会保持行和列的结构。
# Tidy OD matrix
df <- data.frame (origin = c(rep("A",3),rep("B",rep("C",3)),destination = rep(c("A","B","C"),value = c(0,1,10,5,11,15,6,0))
# Weights
wdf <- data.frame(region = c("A",w = c(1,2,3))
# Add weights to the data.
plot_df <- df %>%
merge(wdf %>% rename(w_origin = w),by.x = 'origin',by.y = 'region') %>%
merge(wdf %>% rename(w_destination = w),by.x = 'destination',by.y = 'region')
数据如下所示:
> plot_df
destination origin value w_origin w_destination
1 A A 0 1 1
2 A C 15 3 1
3 A B 5 2 1
4 B A 1 1 2
5 B B 0 2 2
6 B C 6 3 2
7 C B 11 2 3
8 C A 10 1 3
9 C C 0 3 3
但是,当在 width
中将权重作为 height
和 aes()
传递时,我得到了:
ggplot(plot_df,aes(x = destination,y = origin)) +
geom_tile(
aes(
width = w_destination,height = w_origin,fill = value),color = 'black')
它似乎适用于列的大小(宽度),但不完全是因为比例不正确。而且这些行到处都是,没有对齐。
我只使用 geom_tile
是因为我可以通过 height
和 width
作为美学,但我接受其他建议。
解决方法
所以我想我为您提供了部分解决方案。在使用了 geom_tile 之后,当您使用高度和宽度时,数据框的顺序似乎很重要。
这是我想出的一些示例代码(先运行你的代码)。我将您的 data_frame 转换为 tibble(dplyr 的一部分),以便更轻松地按列排序。
# Converted your dataframe to a tibble dataframe
plot_df_tibble = tibble(plot_df)
# Sorted your dataframe by your w_origin column:
plot_df_tibble2 = plot_df_tibble[order(plot_df_tibble$w_origin),]
# Plotted the sorted data frame:
ggplot(plot_df_tibble2,aes(x = destination,y = origin)) +
geom_tile(
aes(
width = w_destination,height = w_origin,fill = value),color = 'black')
得到这个情节: Link to image I made
我应该注意,如果您在排序之前运行转换后的 tibble,您会得到与您发布的相同的图。
对于 geom_tile 的这一部分,似乎高度和宽度的争论可能没有完全发展,因为我觉得 df 的顺序应该无关紧要。 干杯
,问题在于您的图块重叠。原因是虽然您可以将宽度和高度作为美学传递,但 geom_tile
不会为您调整瓷砖的 x 和 y 位置。当您在 x 和 y 上映射离散变量时,您的瓷砖位于等距网格上。在您的情况下,图块位于 0.5、1.5 和 2.5。然后以指定的宽度和高度在这些位置绘制图块。
通过为您的绘图添加一些透明度可以很容易地看到这一点:
library(ggplot2)
library(dplyr)
ggplot(plot_df,color = "black",alpha = .2)
要获得所需的结果,您必须根据所需的宽度和高度手动计算 x 和 y 位置,以防止框重叠。为此,您可以切换到连续比例并通过 scale_x/y_ continuous
:
breaks <- wdf %>%
mutate(cumw = cumsum(w),pos = .5 * (cumw + lag(cumw,default = 0))) %>%
select(region,pos)
plot_df <- plot_df %>%
left_join(breaks,by = c("origin" = "region")) %>%
rename(y = pos) %>%
left_join(breaks,by = c("destination" = "region")) %>%
rename(x = pos)
ggplot(plot_df,aes(x = x,y = y)) +
geom_tile(
aes(
width = w_destination,color = "black") +
scale_x_continuous(breaks = breaks$pos,labels = breaks$region,expand = c(0,0.1)) +
scale_y_continuous(breaks = breaks$pos,0.1))