R - 在条形图中按组大小加权

R - Weighting by group size in bar charts

假设我有一个如下所示的数据框:

groups <- floor(runif(1000, min=1, max=5))
activity <- rep(c("A1", "A2", "A3", "A4"), times= 250)
endorsement <- floor(runif(1000, min=0, max=2))
value1 <- runif(1000, min=1, max=10)
area <- rep(c("A", "A", "A", "A", "B", "C", "C", "D", "D", "E"), times = 100)

df <- data.frame(groups, activity, endorsement, value1, area)

印刷:

> head(df)
  groups activity endorsement   value1 area
1      1       A1           0 7.443375    A
2      1       A2           0 4.342376    A
3      1       A3           0 4.810690    A
4      4       A4           0 3.494974    A
5      3       A1           1 6.442354    B
6      1       A2           0 9.794138    C

我想计算一些描述性统计数据并创建一些条形图,但是如果您查看 area 变量,A 的表现非常好,而 BE 不是。

我对 area 变量本身不感兴趣,但 stats/plot 将由数据集中具有高代表性的区域驱动,因此我需要对数据进行加权,但我'我不确定在以下情况下的正确方法:

平均值和标准差

我正在计算平均值和 SD 或 value1 如下:

df %>% group_by(groups) %>% summarise(mean=mean(value1), sd=sd(value1))

计算加权 mean/sd 以补偿每个区域样本量差异的正确方法是什么(即我想给每个 area 相同的权重)?

堆积条形图

ggplot(df, aes(groups)) +
  geom_bar(aes(fill = activity), position = position_fill(reverse = F))

条形表示每个 activity 在每个 group 中出现的频率比例。同样,这主要是由 A 区的受访者推动的——有没有办法平衡这一点并计算比例,就好像 area 具有同等代表性?

分组均值

ggplot(aes(x = activity, y = value1, fill=factor(groups)), data=df) +
  geom_bar(position="dodge", stat="summary", fun.y="mean")+
  guides(fill = guide_legend(reverse=F, title="group"))

条形表示每个 groupactivity 组合的 value1 的平均值。同样,这些平均值的加权有利于 A 区,并且代表性不相等

分组计数比例

summary_df <- df %>% group_by(groups, activity) %>%
    summarise(n=n(), count=sum(endorsement)) %>% mutate(prop=(count/n)*100)

ggplot(aes(x = activity, y = prop, fill = factor(groups)), data=summary_df) +
  geom_bar(width=0.8, position = position_dodge(width=0.8), stat="identity") +
  guides(fill = guide_legend(reverse=F, title="group"))

对于每个 groupactivity 组合,我正在计算支持该项目(回复 1)的人数,并计算总人数的比例小组

上面的4个问题都源于同一个问题,都需要area加权才能创造平等的代表性。但是,可视化的创建方式各不相同,显示的内容也不同(均值、堆叠条形图、分组均值、计数比例),我不确定在每种情况下解释样本量差异的正确方法。是否有一个单一的修复程序会传播到每个图形示例?

一个策略是 down-up-sample 你的 dataframe 这样每个区域都有相同的数字的观察。我们可以使用 caret 包中的便利函数 downSample()upSample(),根据文档:

"Simple random sampling is used to down-sample for the majority class(es). Note that the minority class data are left intact..."

举例说明:

library(dpyr)
library(caret)
# Before
df %>% group_by(area) %>% summarise(n())
#   area `n()`
#1      A   400
#2      B   100
#3      C   200
#4      D   200
#5      E   100

# After
set.seed(123)
test_down <- downSample(df, df$area)
test_down %>% group_by(area) %>% summarise(n())
#    area `n()`
#1      A   100
#2      B   100
#3      C   100
#4      D   100
#5      E   100

test_up <- upSample(df, df$area)
test_up %>% group_by(area) %>% summarise(n())
#    area `n()`
#1      A   400
#2      B   400
#3      C   400
#4      D   400
#5      E   400

那么你的第一张图就变成了:

library(ggplot2)
ggplot(test_down, aes(groups)) +
        geom_bar(aes(fill = activity), 
                 position = position_fill(reverse = F))

请注意,因为我们使用随机抽样,所以我们无法控制在使用 downSample() 时忽略了哪些观察结果。因此,在没有 set.seed().

的情况下,每个 运行 的结果可能看起来略有不同