创建堆积图
Creating stacked chart
我有两个 table 用于存储用户的登录尝试。一个 table 包含所有成功的登录,另一个包含失败的尝试。我正在尝试使用失败登录计数和成功登录计数来创建堆积图。这就是我的 table 的样子:
Success_login Table:
User_ID Site_Address Login_Attempts
1 xxx.xxx.xxx 5
2 xxx.xxy.yyy 10
Fail_login Table:
User_ID Site_Address Login_Attempts
1 xxx.xxx.xxx 2
2 xxx.xxy.yyy 8
如何使用这两个 table 的 Login_Attempts 列来创建堆积图,以便突出显示成功和失败的尝试?我上网查了一下,发现了这段代码:
# Stacked Bar Plot with Colors and Legend
counts <- table(mtcars$vs, mtcars$gear)
barplot(counts, main="Car Distribution by Gears and VS",
xlab="Number of Gears", col=c("darkblue","red"),
legend = rownames(counts))
但是,它不起作用,因为我的两个 table 有不同的记录数。如果您能指导我找到解决方案,我将不胜感激。
谢谢
- 尝试手绘您要创建的堆叠图。它甚至有意义吗?
- 当确信您现在知道您想要的结果应该是什么样子时,手动创建一个 单个 data.frame 或
barplot
所需的矩阵创建你的结果。请记住包括特殊情况,例如用户只有成功或不成功的登录。
- 图解如何将您的输入 data.frame 放在上一步中的单个 data.frame 中。
第 2 步的结果是您需要的可重现示例,以便在这里提出一个明智的问题。
第 3 步是你在这里问的,但你似乎不确定中间结果应该是什么样子。
第 1 步是关于可视化最终产品,然后从那里开始工作。
讨论
首先,您必须将您的数据统一为一个 table。如果您熟悉 SQL,这可以通过一种外部连接来完成。参见 How to join (merge) data frames (inner, outer, left, right)?。生成的 NA
s(对于未能连接到相反 table 的记录)必须替换为零,以便最终调用 barplot()
工作。
然后,您必须按照 barplot()
要求的格式导出矩阵以生成堆叠条形图,只需调用 matrix()
即可轻松完成。注意正确设置labels/titles/legends/colors,你可以得到一个漂亮的堆叠条形图:
代码
s <- data.frame(User_ID=c(1,2,3), Site_Address=c('xxx.xxx.xxx','xxx.xxy.yyy','xxx.yyy.zzz'), Login_Attempts=c(5,10,3) );
f <- data.frame(User_ID=c(1,2,4), Site_Address=c('xxx.xxx.xxx','xxx.xxy.yyy','xxx.yyy.zzz'), Login_Attempts=c(2,8,4) );
all <- merge(s,f,by=c('User_ID','Site_Address'),suffixes=c('.successful','.failed'),all=T);
all[is.na(all)] <- 0;
stackData <- matrix(c(all$Login_Attempts.failed, all$Login_Attempts.successful ),2,byrow=T);
colnames(stackData) <- paste0(all$User_ID, '@', all$Site_Address );
rownames(stackData) <- c('failed','successful');
barplot(stackData,main='Successful and failed login attempts',xlab='User_ID@Site_Address',ylab='Login_Attempts',col=c('red','blue'),legend=rownames(stackData));
结果数据
r> s;
User_ID Site_Address Login_Attempts
1 1 xxx.xxx.xxx 5
2 2 xxx.xxy.yyy 10
3 3 xxx.yyy.zzz 3
r> f;
User_ID Site_Address Login_Attempts
1 1 xxx.xxx.xxx 2
2 2 xxx.xxy.yyy 8
3 4 xxx.yyy.zzz 4
r> all;
User_ID Site_Address Login_Attempts.successful Login_Attempts.failed
1 1 xxx.xxx.xxx 5 2
2 2 xxx.xxy.yyy 10 8
3 3 xxx.yyy.zzz 3 0
4 4 xxx.yyy.zzz 0 4
r> stackData;
1@xxx.xxx.xxx 2@xxx.xxy.yyy 3@xxx.yyy.zzz 4@xxx.yyy.zzz
failed 2 8 0 4
successful 5 10 3 0
输出
参考资料
- How to join (merge) data frames (inner, outer, left, right)?
- R: merge unequal dataframes and replace missing rows with 0
- https://stat.ethz.ch/R-manual/R-devel/library/base/html/merge.html
- http://www.statmethods.net/graphs/bar.html
- https://stat.ethz.ch/R-manual/R-devel/library/graphics/html/barplot.html
- https://stat.ethz.ch/R-manual/R-devel/library/base/html/matrix.html
编辑:创建单柱堆叠条形图有点奇怪,但是好吧,下面是你如何做的,使用上面的数据(all
) 作为基础:
barplot(matrix(c(sum(all$Login_Attempts.failed),sum(all$Login_Attempts.successful))),main='Successful and failed login attempts',ylab='Login_Attempts',col=c('red','blue'),legend=c('failed','successful'));
编辑: 是的,默认情况下 y 轴确实应该完全覆盖堆栈,这是基本图形包中的一个弱点,它没有。您可以将 ylim=c(0,1.2*sum(do.call(c,all[,3:4])))
作为参数添加到 barplot()
调用以强制 y 轴超出堆栈的高点至少 20%。 (不幸的是,您必须根据输入数据手动计算,但正如我所说,这是包中的一个弱点。)
此外,关于我对条形单一性的评论,堆叠条形图更常用于比较多个条形,而不是显示单个条形。 (这就是为什么我最初的假设是您希望每个 user/site 都有一个单独的条形图。)通常您会看到一个普通的旧条形图,并排显示不同的数据点,而不是单个堆叠的条形图。但这实际上取决于您的应用程序,因此请选择最适合您的方法。
我有两个 table 用于存储用户的登录尝试。一个 table 包含所有成功的登录,另一个包含失败的尝试。我正在尝试使用失败登录计数和成功登录计数来创建堆积图。这就是我的 table 的样子:
Success_login Table:
User_ID Site_Address Login_Attempts
1 xxx.xxx.xxx 5
2 xxx.xxy.yyy 10
Fail_login Table:
User_ID Site_Address Login_Attempts
1 xxx.xxx.xxx 2
2 xxx.xxy.yyy 8
如何使用这两个 table 的 Login_Attempts 列来创建堆积图,以便突出显示成功和失败的尝试?我上网查了一下,发现了这段代码:
# Stacked Bar Plot with Colors and Legend
counts <- table(mtcars$vs, mtcars$gear)
barplot(counts, main="Car Distribution by Gears and VS",
xlab="Number of Gears", col=c("darkblue","red"),
legend = rownames(counts))
但是,它不起作用,因为我的两个 table 有不同的记录数。如果您能指导我找到解决方案,我将不胜感激。
谢谢
- 尝试手绘您要创建的堆叠图。它甚至有意义吗?
- 当确信您现在知道您想要的结果应该是什么样子时,手动创建一个 单个 data.frame 或
barplot
所需的矩阵创建你的结果。请记住包括特殊情况,例如用户只有成功或不成功的登录。 - 图解如何将您的输入 data.frame 放在上一步中的单个 data.frame 中。
第 2 步的结果是您需要的可重现示例,以便在这里提出一个明智的问题。 第 3 步是你在这里问的,但你似乎不确定中间结果应该是什么样子。 第 1 步是关于可视化最终产品,然后从那里开始工作。
讨论
首先,您必须将您的数据统一为一个 table。如果您熟悉 SQL,这可以通过一种外部连接来完成。参见 How to join (merge) data frames (inner, outer, left, right)?。生成的 NA
s(对于未能连接到相反 table 的记录)必须替换为零,以便最终调用 barplot()
工作。
然后,您必须按照 barplot()
要求的格式导出矩阵以生成堆叠条形图,只需调用 matrix()
即可轻松完成。注意正确设置labels/titles/legends/colors,你可以得到一个漂亮的堆叠条形图:
代码
s <- data.frame(User_ID=c(1,2,3), Site_Address=c('xxx.xxx.xxx','xxx.xxy.yyy','xxx.yyy.zzz'), Login_Attempts=c(5,10,3) );
f <- data.frame(User_ID=c(1,2,4), Site_Address=c('xxx.xxx.xxx','xxx.xxy.yyy','xxx.yyy.zzz'), Login_Attempts=c(2,8,4) );
all <- merge(s,f,by=c('User_ID','Site_Address'),suffixes=c('.successful','.failed'),all=T);
all[is.na(all)] <- 0;
stackData <- matrix(c(all$Login_Attempts.failed, all$Login_Attempts.successful ),2,byrow=T);
colnames(stackData) <- paste0(all$User_ID, '@', all$Site_Address );
rownames(stackData) <- c('failed','successful');
barplot(stackData,main='Successful and failed login attempts',xlab='User_ID@Site_Address',ylab='Login_Attempts',col=c('red','blue'),legend=rownames(stackData));
结果数据
r> s;
User_ID Site_Address Login_Attempts
1 1 xxx.xxx.xxx 5
2 2 xxx.xxy.yyy 10
3 3 xxx.yyy.zzz 3
r> f;
User_ID Site_Address Login_Attempts
1 1 xxx.xxx.xxx 2
2 2 xxx.xxy.yyy 8
3 4 xxx.yyy.zzz 4
r> all;
User_ID Site_Address Login_Attempts.successful Login_Attempts.failed
1 1 xxx.xxx.xxx 5 2
2 2 xxx.xxy.yyy 10 8
3 3 xxx.yyy.zzz 3 0
4 4 xxx.yyy.zzz 0 4
r> stackData;
1@xxx.xxx.xxx 2@xxx.xxy.yyy 3@xxx.yyy.zzz 4@xxx.yyy.zzz
failed 2 8 0 4
successful 5 10 3 0
输出
参考资料
- How to join (merge) data frames (inner, outer, left, right)?
- R: merge unequal dataframes and replace missing rows with 0
- https://stat.ethz.ch/R-manual/R-devel/library/base/html/merge.html
- http://www.statmethods.net/graphs/bar.html
- https://stat.ethz.ch/R-manual/R-devel/library/graphics/html/barplot.html
- https://stat.ethz.ch/R-manual/R-devel/library/base/html/matrix.html
编辑:创建单柱堆叠条形图有点奇怪,但是好吧,下面是你如何做的,使用上面的数据(all
) 作为基础:
barplot(matrix(c(sum(all$Login_Attempts.failed),sum(all$Login_Attempts.successful))),main='Successful and failed login attempts',ylab='Login_Attempts',col=c('red','blue'),legend=c('failed','successful'));
编辑: 是的,默认情况下 y 轴确实应该完全覆盖堆栈,这是基本图形包中的一个弱点,它没有。您可以将 ylim=c(0,1.2*sum(do.call(c,all[,3:4])))
作为参数添加到 barplot()
调用以强制 y 轴超出堆栈的高点至少 20%。 (不幸的是,您必须根据输入数据手动计算,但正如我所说,这是包中的一个弱点。)
此外,关于我对条形单一性的评论,堆叠条形图更常用于比较多个条形,而不是显示单个条形。 (这就是为什么我最初的假设是您希望每个 user/site 都有一个单独的条形图。)通常您会看到一个普通的旧条形图,并排显示不同的数据点,而不是单个堆叠的条形图。但这实际上取决于您的应用程序,因此请选择最适合您的方法。