【问题标题】:Plotting a bivariate to multiple factors in R在 R 中为多个因子绘制双变量
【发布时间】:2023-03-17 10:25:01
【问题描述】:

首先,我还是个初学者。我正在尝试用 R 解释和绘制堆栈条形图。我已经查看了许多答案,但有些答案并不针对我的案例,有些我根本不明白:

我有一个数据集dvl,它有五列,Variant、Region、Time、Person 和 PrecededByPrep。我想对 Variant 与其他四个预测变量进行多变量比较。每列可以有两个可能的值之一:

  • 变体:elkieder
  • 地区 = VLNL
  • 时间:timeno time
  • 人员:personno person
  • PrecededByPrep:10

这是逻辑回归

从我收集到的答案中,ggplot2 库可能是最好的绘图库。我已经阅读了它的文档,但对于我的生活,我无法弄清楚如何绘制这个:如何将 Variant 与其他三个因素进行比较?

我花了一些时间,但我在 Photoshop 中做出了与我想要的相似的东西(虚构的价值!)。

深灰色/浅灰色:Variant 的可能值 y轴:频率 x 轴:每一列,细分为可能的值

我知道制作单独的条形图,both stacked and grouped,但基本上我不知道如何制作堆叠的、分组的条形图。 ggplot2 可以用,但如果不用我更喜欢。

我认为这可以看作是一个示例数据集,尽管我并不完全确定。我是 R 的初学者,我阅读了有关创建样本集的信息。

t <- data.frame(Variant = sample(c("iedere","elke"),size = 50, replace = TRUE),
            Region = sample(c("VL","NL"),size = 50, replace = TRUE),
            PrecededByPrep = sample(c("1","0"),size = 50, replace = TRUE),
            Person = sample(c("person","no person"),size = 50, replace = TRUE),
            Time = sample(c("time","no time"),size = 50, replace = TRUE))

我也想让情节在美学上令人愉悦。我的想法:

  • 绘制颜色(即用于条形图):col=c("paleturquoise3", "palegreen3")
  • 轴标签font.lab=2 为粗体,但值标签不是(例如,'regionin bold, butVLandNL` 不是粗体)
  • #404040 作为字体、轴和线的颜色
  • 轴标签:x:factors,y:frequency

【问题讨论】:

  • 小点:拥有多个预测变量不会使您的分析“多变量”;这是 1970 年代的常见用法,但不再是。我已将“二价”编辑为“二进制”。
  • 大点:看来您本质上是在要求R代码。这将使其偏离主题:请参阅帮助中心以获取有关软件相关问题的建议。可以使这更具统计性,但是您需要扩展您想象的绘图类型;目前它完全是开放式的,因此可以说太宽泛了。
  • @NickCox 请看我的编辑,我付出了很多努力,所以我希望它足以提出一个更可行的问题。
  • thisthis 对您有帮助吗?
  • @Tim 并非如此,因为这些链接无法帮助将图形堆叠和分组。只有单独的可能性。

标签: r data-visualization ggplot2


【解决方案1】:

这是一种可能性,它从“未列出的”数据框 melt 它开始,在 ggplot2 中使用 geom_bar 绘制它(它对每组进行计数),通过使用按变量分隔图facet_wrap.

创建玩具数据:

set.seed(123)
df <- data.frame(Variant = sample(c("iedere", "elke"), size = 50, replace = TRUE),
           Region = sample(c("VL", "NL"), size = 50, replace = TRUE),
           PrecededByPrep = sample(c("1", "0"), size = 50, replace = TRUE),
           Person = sample(c("person", "no person"), size = 50, replace = TRUE),
           Time = sample(c("time", "no time"), size = 50, replace = TRUE))

重塑数据:

library(reshape2)
df2 <- melt(df, id.vars = "Variant")

剧情:

library(ggplot2)
ggplot(data = df2, aes(factor(value), fill = Variant)) +
  geom_bar() +
  facet_wrap(~variable, nrow = 1, scales = "free_x") +
  scale_fill_grey(start = 0.5) +
  theme_bw()

有很多自定义绘图的机会,例如setting order of factor levelsrotating axis labelswrapping facet labels on two lines(例如更长的变量名称“PrecededByPrep”)或changing spacing between facets

自定义(在相关更新和 OP 的 cmets 之后)

# labeller function used in facet_grid to wrap "PrecededByPrep" on two lines
# see http://www.cookbook-r.com/Graphs/Facets_%28ggplot2%29/#modifying-facet-label-text
my_lab <- function(var, value){
  value <- as.character(value)
    if (var == "variable") { 
      ifelse(value == "PrecededByPrep", "Preceded\nByPrep", value)
    }
}

ggplot(data = df2, aes(factor(value), fill = Variant)) +
  geom_bar() +
  facet_grid(~variable, scales = "free_x", labeller = my_lab) + 
  scale_fill_manual(values = c("paleturquoise3", "palegreen3")) + # manual fill colors
  theme_bw() +
  theme(axis.text = element_text(face = "bold"), # axis tick labels bold 
        axis.text.x = element_text(angle = 45, hjust = 1), # rotate x axis labels
        line = element_line(colour = "gray25"), # line colour gray25 = #404040
        strip.text = element_text(face = "bold")) + # facet labels bold  
  xlab("factors") + # set axis labels
  ylab("frequency")

向每个条形添加计数(从 OP 编辑​​以下 cmets)。

计算y坐标的基本原理见this Q&A。这里我使用dplyr 来计算每根柱的计数(即geom_text 中的label)及其y 坐标,但这当然可以在base R、plyrdata.table 中完成。

# calculate counts (i.e. labels for geom_text) and their y positions.
library(dplyr)
df3 <- df2 %>%
  group_by(variable, value, Variant) %>%
  summarise(n = n()) %>%
  mutate(y = cumsum(n) - (0.5 * n))

# plot
ggplot(data = df2, aes(x = factor(value), fill = Variant)) +
  geom_bar() +
  geom_text(data = df3, aes(y = y, label = n)) +
  facet_grid(~variable, scales = "free_x", labeller = my_lab) + 
  scale_fill_manual(values = c("paleturquoise3", "palegreen3")) + # manual fill colors
  theme_bw() +
  theme(axis.text = element_text(face = "bold"), # axis tick labels bold 
        axis.text.x = element_text(angle = 45, hjust = 1), # rotate x axis labels
        line = element_line(colour = "gray25"), # line colour gray25 = #404040
        strip.text = element_text(face = "bold")) + # facet labels bold  
  xlab("factors") + # set axis labels
  ylab("frequency")

【讨论】:

  • 这已经非常接近我想要的了。我用一些关于情节美学的额外信息编辑了我的 OP。你也可以考虑这些吗?是否有可能与价值观不重叠? (例如,PrecededByPrep 列太宽以至于可以容纳标签 PrecededByPrep(没有溢出),Person 太宽以至于可以容纳值 no personperson 的文本)。我应该在前面提到这一点,但当时并没有考虑情节的外观。对不起。
  • 这看起来很棒!我正在尝试对其进行一些编辑,但我不知道如何定位特定标签。例如,我怎样才能给Region 提供另一种颜色和另一种背景颜色?
  • 在 SO 上有很多关于构面及其条带的条件格式的帖子。参见例如herehere.
  • 虽然它不属于我的原始答案,但我想知道(正如您可能已经从我的其他答案中注意到的那样)是否有一种方法可以将值添加到不同的条形图,以及绿色蓝色。
  • 很高兴听到它以您想要的方式工作!关于学习R,我想你知道有很多免费的文档here。此外,当涉及到“非常结构”时,您可以查看“对象”和“动作”部分 here 以及“基础”部分中的前几章“章节”here
【解决方案2】:

这是我提出的具有基数 R 的函数 barplot 的解决方案:

1.计算计数

l_count_df<-lapply(colnames(t)[-1],function(nomcol){table(t$Variant,t[,nomcol])})
count_df<-l_count_df[[1]]
for (i in 2:length(l_count_df)){
    count_df<-cbind(count_df,l_count_df[[i]])
}

2。绘制没有轴名称的条形图,保存条形坐标

par(las=1,col.axis="#404040",mar=c(5,4.5,4,2),mgp=c(3.5,1,0))
bp<-barplot(count_df,width=1.2,space=rep(c(1,0.3),4),col=c("paleturquoise3", "palegreen3"),border="#404040", axisname=F, ylab="Frequency",
            legend=row.names(count_df),ylim=c(0,max(colSums(count_df))*1.2))

3.标记条形

mtext(side=1,line=0.8,at=bp,text=colnames(count_df))
mtext(side=1,line=2,at=(bp[seq(1,8,by=2)]+bp[seq(2,8,by=2)])/2,text=colnames(t)[-1],font=2)

4.在条内添加值

for(i in 1:ncol(count_df)){
    val_elke<-count_df[1,i]
    val_iedere<-count_df[2,i]
    text(bp[i],val_elke/2,val_elke)
    text(bp[i],val_elke+val_iedere/2,val_iedere)
}

这是我得到的(使用我的随机数据):

【讨论】:

  • 您的最后一个命令是否可能不完整? R 似乎不想运行它。编辑:你最后错过了一个括号!
  • @BramVanroy 好的,我的答案末尾有一个括号,我想知道它在那里做什么(所以我删除了它......)但我只是在结束之前包含了图片最后一条指令的括号......真的很抱歉! (已更正)
  • 我正在考虑接受这个,因为它不需要任何库。 (+1!)太棒了!是否可以 1. 用“频率”标记 y 轴,并在标签和值之间留出更多空间(例如,区域和 NL/VL 之间)。
  • 谢谢!!您可以用ylab 标记yaxis,并用线条控制标签之间的空间。我将更改参数。告诉我是否可以
  • 中间和旋转没问题,虽然到轴的距离可能会大一些。 IE。 “频率”离 y 轴稍远一些。这可能吗?
【解决方案3】:

我基本上是在回答一个不同的问题。我想这可以被视为我的反常,但我真的不喜欢几乎任何类型的条形图。它们似乎总是造成浪费空间,因为目前的信息数值不如适当构造的表格有用。 vcd 包提供了一个扩展的镶嵌图函数,在我看来,它更准确地称为“我迄今为止所见过的任何一个多变量条形图。它确实需要您首先构建一个列联表,其中 xtabs函数似乎非常合适。

install.packages)"vcd")
library(vcd)
help(package=vcd,mosaic)
col=c("paleturquoise3", "palegreen3")
vcd::mosaic(xtabs(~Variant+Region + PrecededByPrep   +  Time, data=ttt) 
           ,highlighting="Variant", highlighting_fill=col)

这是 5 路图,这是 5 路图:

png(); vcd::mosaic( xtabs(
                  ~Variant+Region + PrecededByPrep +   Person  +  Time, 
                   data=ttt) 
                ,highlighting="Variant", highlighting_fill=col); dev.off()

【讨论】:

  • 感谢您的回答。我考虑过马赛克图,但我认为它不像条形图那样清晰,尽管您说它们节省更多空间是对的。
猜你喜欢
  • 2013-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-14
  • 2023-04-09
  • 2018-06-24
相关资源
最近更新 更多