我有分类数据,我想要映射使用热图(geom_tile)的频率,非常类似于下面的示例:
data("mtcars")
freq <- data.frame(xtabs(~cyl + gear, mtcars)) #count number of 4,6,8 cyl cars by gear
ggplot(freq, aes(cyl, gear)) +
geom_tile(aes(fill = Freq)) +
scale_fill_gradient(low = "white",high = "steelblue")
但我想根据重要或非重要结果(0-1值)的比例分割每个图块。在这个例子中,我会生成相同的频率计数但区分自动和手动传输(am
)
freq_am <- data.frame(xtabs(~cyl + gear + am, mtcars))
print(freq_am)
#cyl gear am Freq
4 3 0 1
6 3 0 2
8 3 0 12
4 4 0 2
6 4 0 2
8 4 0 0
4 5 0 0
6 5 0 0
8 5 0 0
4 3 1 0
6 3 1 0
8 3 1 0
4 4 1 6
6 4 1 2
8 4 1 0
4 5 1 2
6 5 1 1
8 5 1 2
对于am==0
,生成的热图将具有(例如) blue ,用于am==1
和 red 的值。根据自动(am==0
)或手动(am==1
)的那种类型的汽车比例,每个瓷砖将被划分(沿对角线?)。蓝色和红色的阴影将与计数成比例,就像渐变已经反映出来一样。
例如:
左上方的瓷砖(4,5)将是完全浅红色,因为所有4缸,5档汽车(计数= 2)都是手动的
左中间瓷砖(4,4)为1/4蓝色和3/4红色,因为25%的4档4缸汽车是自动的(计数= 2),75%是手册(计数= 6)
左下方的瓷砖(4,3)将是完全最轻的蓝色,因为所有4缸,3档汽车(计数= 1)都是自动的
答案 0 :(得分:3)
这是第二次并且完全尝试通过操纵频率计数来回答问题,以便它们变为am==1
的负数。与first attempt的区别在于使用geom_col(position = "fill")
代替geom_tile()
进行绘图。
注意:我没有编辑the first answer,因为OP已经对它进行了评论,我最终可能会删除第一个和不完整的答案。
freq_am <-data.frame(xtabs(~cyl + gear + am, mtcars))
freq_am$Freq_am <- freq_am$Freq * (-1)^as.integer(as.character(freq_am$am))
如果Freq_am
(手动),则会创建一个新列Freq
,其中-1
计数乘以am == 1
。使用逻辑值取幂是避免ifelse
的一种技巧。
有两种可能性来实现所需的热图外观。
p <- ggplot(freq_am, (aes(x = cyl, y = Freq, fill = Freq_am))) +
geom_col(position = "fill", width = 1) +
scale_fill_gradient2() +
facet_grid(gear ~ ., as.table = FALSE, switch = "y") +
scale_y_continuous(expand = c(0, 0)) +
scale_x_discrete(expand = c(0, 0))
p
使用Freq
创建cyl
与geom_col()
的堆积条形图,其中条形图垂直拉伸(position = "fill"
)和水平拉伸(width = 1
)填写绘图区域。此外,expand = c(0, 0)
函数的scale
参数告诉ggplot
不像往常一样展开轴。请注意,x轴是离散的,因为xtabs()
已将cyl
强制为因子。
facet_grid()
用于模拟y轴,grid
值按递增顺序(as.table = FALSE
)。 switch = "y"
将面板条移动到左侧。
scale_fill_gradient2()
默认使用方便的分色配色方案,以便自动变速器的车辆数量显示为蓝色,手动变速器的车辆数量显示为红色。
现在,我们需要删除热图所不需要的所有装饰和空间。最后,重命名y轴标签:
p + theme(panel.grid = element_blank()
, axis.ticks = element_blank()
, axis.text.y = element_blank()
, strip.background = element_blank()
, panel.spacing.y = unit(0, "pt")
) +
ylab("gear")
这种方法的缺点是瓷砖之间缺乏边界。因此,如果相邻的瓷砖具有相同的颜色,例如6缸,3档和4档,则很难区分计数的份额。
此变体在图块之间添加边框。边框的宽度可以灵活调整:
p <- ggplot(freq_am, (aes(x = 1, y = Freq, fill = Freq_am))) +
geom_col(position = "fill") +
scale_fill_gradient2() +
facet_grid(gear ~ cyl, as.table = FALSE, switch = "both") +
scale_y_continuous(expand = c(0, 0)) +
scale_x_continuous(expand = c(0, 0))
p
在这里,我们将facet_grid()
用于两个方向。对于每个面板,如上所述使用Freq
绘制1
与虚拟变量geom_col()
的关系。由于虚拟变量1
是数字,我们不需要width
参数geom_col()
。两个轴现在都是连续的。
同样,我们需要删除一些装饰并重命名x和y轴上的标签:
p + theme(panel.grid = element_blank()
, axis.ticks = element_blank()
, axis.text = element_blank()
, strip.background = element_blank()
# , panel.spacing = unit(0, "pt")
) +
xlab("cyl") + ylab("gear")
现在,我们确实有一个瓷砖之间有边框的热图。要删除边框或调整宽度,您可以使用panel.spacing
取消注释该行并更改该值。
答案 1 :(得分:1)
这是首次尝试通过操纵频率计数找到Q的(不完整)答案,使它们对am==0
变为负数。
请注意,问题并不完全清楚。 ?mtcars
将am
定义为
传输(0 =自动,1 =手动)。
虽然OP已定义
自动(
am==1
)或手动(am==0
)
这恰恰相反。此外,OP已请求热图显示{em>蓝色以显示am==1
的值am==0
和红色。
freq_am <-data.frame(xtabs(~cyl + gear + am, mtcars))
freq_am$Freq_am <- -freq_am$Freq * (-1)^as.integer(as.character(freq_am$am))
freq_am$gear_am <- factor(paste(as.character(freq_am$gear), as.character(freq_am$am), sep = "_"))
freq_am
#freq_am
# cyl gear am Freq Freq_am gear_am
#1 4 3 0 1 -1 3_0
#2 6 3 0 2 -2 3_0
#3 8 3 0 12 -12 3_0
#4 4 4 0 2 -2 4_0
#5 6 4 0 2 -2 4_0
#6 8 4 0 0 0 4_0
#7 4 5 0 0 0 5_0
#8 6 5 0 0 0 5_0
#9 8 5 0 0 0 5_0
#10 4 3 1 0 0 3_1
#11 6 3 1 0 0 3_1
#12 8 3 1 0 0 3_1
#13 4 4 1 6 6 4_1
#14 6 4 1 2 2 4_1
#15 8 4 1 0 0 4_1
#16 4 5 1 2 2 5_1
#17 6 5 1 1 1 5_1
#18 8 5 1 2 2 5_1
请注意xtabs()
已强制am
因素:
str(freq_am$am)
# Factor w/ 2 levels "0","1": 1 1 1 1 1 1 1 1 1 2 ...
要将am
转换为数字,我们必须使用as.integer(as.character(freq_am$am))
。 (您可以使用(as.integer(am) - 1)
将关卡编号直接转换为原始数值,但这样可以减少保存。)
gear_am
将用作新的y轴。
library(ggplot2)
ggplot(freq_am, aes(cyl, gear_am, fill = Freq_am)) +
geom_tile() +
scale_fill_gradient2() +
theme_minimal() +
theme(panel.grid = element_blank())
默认情况下, scale_fill_gradient2()
使用方便的分散颜色方案。
现在,y轴上gear
的切片已被分割为am==0
和am==1
的切片。
OP已经要求即使零计数也应该完全填充现在拆分的区块。这可以通过进一步操纵freq_am
来实现。但是,我发现当前图表以清晰,不明确的方式传达结果。