首页 > 解决方案 > 如何在 R 中绘制评分量表

问题描述

表示以下特质评分量表的最佳方式是什么?我想标记民主党和共和党的特征(8 个特征)和程度或每种情绪(1 表示情绪低落,5 表示强烈情绪)?我需要汇总项目吗?我是 R 新手,不知道如何解决这个问题。

调查问题和规模:

“以下是可能由物体引起的感受或情绪的列表。请使用下面的列表来描述美国联邦政党(及其民选官员)给你的感受。如果这个词明确描述了一个政党给你的感受,然后选择数字 5。如果您认为这个词根本无法描述聚会给您的感受,请选择数字 1。使用 1 和 5 之间的中间数字来表示这两个极端之间的反应。

规模

调查样本:

dput(df[Book3(1:nrow(df), 30),])

structure(list(TRAITDEM1 = c(3, 4, 3, 3, 3, 3, 3, 1, 2, 2, 2, 
3, 3, 2, 2, 1, 1, 3, 1, 5, 1, 1, 3, 1, 4, 4, 3, 1, 2, 4), TRAITDEM2 = c(3, 
1, 1, 2, 2, 2, 3, 5, 4, 2, 2, 2, 3, 3, 3, 4, 1, 2, 3, 1, 4, 5, 
2, 3, 1, 1, 1, 4, 1, 2), TRAITDEM3 = c(3, 4, 4, 2, 3, 3, 3, 1, 
1, 2, 2, 3, 3, 2, 2, 1, 1, 3, 1, 5, 1, 1, 3, 1, 4, 5, 4, 1, 3, 
5), TRAITDEM4 = c(3, 2, 1, 2, 2, 2, 4, 5, 4, 5, 2, 3, 2, 3, 3, 
4, 3, 4, 3, 1, 5, 4, 1, 4, 3, 4, 2, 4, 2, 1), TRAITDEM5 = c(3, 
4, 3, 4, 4, 3, 2, 1, 1, 2, 2, 3, 4, 2, 2, 1, 1, 3, 1, 5, 1, 1, 
2, 1, 4, 4, 4, 1, 3, 4), TRAITDEM6 = c(3, 1, 1, 1, 1, 1, 1, 2, 
1, 1, 1, 2, 2, 2, 2, 4, 3, 1, 1, 1, 4, 5, 1, 3, 1, 1, 1, 1, 1, 
1), TRAITDEM7 = c(3, 1, 3, 3, 2, 2, 1, 1, 1, 2, 3, 4, 3, 2, 2, 
1, 1, 2, 2, 5, 1, 1, 1, 3, 3, 4, 2, 1, 5, 5), TRAITDEM8 = c(3, 
1, 1, 1, 2, 1, 3, 5, 2, 4, 1, 1, 2, 2, 3, 1, 3, 1, 2, 1, 5, 5, 
2, 2, 1, 2, 1, 2, 1, 1), TRAITREP1 = c(1, 1, 1, 1, 1, 1, 1, 1, 
1, 4, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 
1), TRAITREP2 = c(1, 5, 5, 5, 5, 5, 5, 2, 5, 2, 5, 5, 5, 5, 4, 
5, 1, 5, 5, 5, 5, 1, 5, 4, 5, 5, 5, 3, 5, 5), TRAITREP3 = c(1, 
1, 1, 1, 2, 1, 1, 2, 1, 4, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 3, 
1, 1, 1, 1, 1, 1, 1, 2), TRAITREP4 = c(1, 5, 5, 1, 5, 5, 5, 3, 
5, 2, 5, 4, 5, 5, 5, 5, 3, 5, 5, 5, 5, 1, 5, 3, 5, 5, 5, 4, 5, 
1), TRAITREP5 = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 2, 
1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 1), TRAITREP6 = c(1, 
5, 5, 5, 3, 3, 3, 1, 1, 1, 3, 3, 5, 3, 4, 5, 3, 4, 5, 4, 5, 1, 
5, 3, 4, 4, 5, 1, 1, 3), TRAITREP7 = c(1, 1, 1, 1, 2, 2, 1, 1, 
1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 
2), TRAITREP8 = c(1, 5, 5, 5, 4, 5, 5, 2, 5, 2, 5, 4, 5, 5, 4, 
1, 3, 5, 5, 5, 5, 3, 4, 4, 5, 5, 5, 3, 5, 5), PARTYID_Strength = c(5, 
1, 2, 1, 2, 1, 8, 7, 6, 3, 1, 6, 6, 1, 7, 8, 7, 1, 1, 1, 2, 4, 
1, 6, 1, 1, 1, 7, 6, 8)), row.names = c(NA, -30L), class = c("tbl_df", 
"tbl", "data.frame"))

“PartyID_Strength”代表政党的 8 个衡量标准:1 - 强大的民主党 2 - 不太强大的民主党 3 - 强大的共和党 4 - 不太强大的共和党 5 - 独立 6 - 独立 - 民主党 7 - 独立 - 共和党 8 - 其他

我尝试过这种方式(下图),但它仍然没有绘制剩余的四个特征:

图表

标签: rggplot2

解决方案


清理数据

为了解决您的问题,我们必须转换您的数据,以便将其转换为整洁的格式。

观察

您的原始数据集存在一些特殊问题:

  • 数据采用宽格式,即数据框中的大部分列可以由 3 个变量表示;
  • 变量的名称不是不言自明的。名称是大写的,它本身不包含任何有用的信息,它们不可读且不适合打字/书写。
  • 我们可以从变量名称中提取更多信息:Party 和Feelings to the Party。第一个是缩写(“dem”或“rep”),第二个是对政党的数字编码感觉。然而,编码感觉的数字顺序并不能反映从厌恶到快乐的情绪的自然顺序;
  • 变量PARTYID_Strength是数字编码的政党 [self-] 标识,它也不反映从最强大的民主党人到独立到最强大的共和党人的自然顺序;

计划

  1. 使用以 开头的所有变量并将变量保持不变,将数据从宽格式转换为格式;TRAITPARTYID_Strength
  2. 从变量中提取有用的信息TRAIT...(政党,对党的感情);
  3. 将所有数字编码的变量转换为具有合理排序水平的因子;
  4. 给所有变量起有意义的名字;
  5. 汇总数据;

转型

我们需要创建几个查找表,这将简化工作流程。

隶属关系查询表:

aff_lookup <- c(
  'Strong Democrat',
  'Not very strong Democrat',
  'Strong Republican',
  'Not very strong Republican',
  'Independent',
  'Independent-Democrat',
  'Independent-Republican',
  'Other'
)

我们可以aff_lookup通过这个向量进一步排序:

aff_order = c(1, 2, 6, 5, 7, 4, 3, 8)

情绪/感受查找表:

emo_lookup <- c(
  'Delighted',    
  'Angry',
  'Happy',
  'Annoyed',
  'Joy',
  'Hateful',
  'Relaxed',
  'Disgusted'
)

我们可以emo_lookup按这个向量排序:

emo_order <- emo_order <- c(8, 6, 2, 4, 7, 3, 1, 5)

政党查询表:

party_lookup <- c(
  dem = 'National Democratic Party',
  rep = 'National Republican Party'
)

最后,使用所有辅助变量,我们可以将数据转换为所需的形式。

library(tidyverse)

dat %<>%
  rename_all(tolower) %>%
  pivot_longer(
    cols          = starts_with('trait'),
    names_to      = c('party', 'emotion'),
    names_pattern = 'trait(dem|rep)(\\d)',
    values_to     = 'score'
  ) %>%
  mutate(
    party = factor(party_lookup[party]),
    affiliation = factor(
      aff_lookup[partyid_strength], 
      levels = aff_lookup[aff_order]
      ),
    emotion = factor(
      emo_lookup[as.numeric(emotion)], 
      levels = emo_lookup[emo_order]
      )
  ) %>%
  group_by(party, emotion, affiliation) %>%
  summarise(score = median(score)) %>%
  ungroup()

head(dat)

## A tibble: 6 x 4
#  party                     emotion   affiliation                score
#  <fct>                     <fct>     <fct>                      <dbl>
#1 National Democratic Party Disgusted Strong Democrat                1
#2 National Democratic Party Disgusted Not very strong Democrat       2
#3 National Democratic Party Disgusted Independent-Democrat           2
#4 National Democratic Party Disgusted Independent                    3
#5 National Democratic Party Disgusted Independent-Republican         3
#6 National Democratic Party Disgusted Not very strong Republican     5

绘制数据

计划

现在我们可以将数据绘制成两个独立的图,分别在 X 轴上为民主党和共和党人(政党认同)和在 Y 轴上的情感(感觉)绘制。

每个 Emotion/Affilation 点将被表示为一个条形,条形的高度代表分数。

我们还可以在绘图中添加颜色编码。从我的角度来看,使用从红色(厌恶)到绿色(喜悦)的颜色渐变来编码情绪/感觉有助于收集我们数据的内部结构。

阴谋

dat %>%
  ggplot(
    aes(
      x      = affiliation, 
      y      = as.numeric(emotion) +  (score / max(score) * .95) / 2, 
      height = (score / max(score) * .95), 
      width  = .95,
      fill   = emotion,
      label  = score
      )
    ) +
  geom_tile(show.legend = FALSE) +
  geom_text(size = 3.5, color = 'gray25', alpha = .75) +
  facet_wrap(~ party, scales = 'free') +
  scale_fill_brewer(palette = 'RdYlGn') +
  scale_y_continuous(breaks = sort(emo_order), labels = emo_lookup[emo_order]) +
  labs(x = 'Affiliations', y = 'Emotions') +
  ggthemes::theme_tufte() +
  theme(
    axis.text.x  = element_text(angle = 45, hjust = 1),
    axis.ticks.x = element_blank(),
    axis.text.y  = element_text(hjust = 0, vjust = -0.025),
    axis.ticks.y = element_blank()
  )

如下图所示:

在此处输入图像描述

解释

这个情节有一个技巧:它看起来像一系列条形图,它不是真正的条形图(事实上,不是功能上的)。

我所做的:

这个解决方案的核心是geom_tile()对每个数据点的使用。它只是一个矩形(默认为正方形),其几何质心由给定坐标(Affilation, Emotion)确定。

Affilation 和 Emotion 都是因素,而不是数字。对于 Affiliation 也是可以的,因为我们只想根据它所代表的 Affiliation来定位我们的图块。

Emotion 更复杂,因为我们想根据它所代表的 Emotion 来定位每个图块,而且我们还想通过图块的高度对 Score 进行编码。

height要定义图块的高度,我们使用aes(). 我们希望我们的图块高度小于或等于 1(偏移量为 0.05),因此 Angry 和 Annoyed 之间的图块不会重叠。这就是我们使用(score / max(score) * .95参数height的原因。

我们还需要为每个图块提供不同的 y 坐标,因此图块的中心不是放置在代表每种情绪的假想线上,而是半高。因此,当绘制瓷砖时,它的中心(在 y 轴上)位于“基线”上方半高的位置,并且瓷砖向上和向下延伸半高,从而创建了一个假条形图。这就是以下代码行的作用 as.numeric(emotion) + (score / max(score) * .95) / 2

我们还给了一个固定宽度为 0.95 by的图块,用红-黄-绿width = .95渐变对图块进行归档,并用相关的分数标记每个图块。

其余的只是装饰品。但是,请注意我们如何关联 Y 轴。因为,正如它定义的那样,aes()它是连续比例尺,但我们想让它成为假的离散轴,我们使用这一行:

scale_y_continuous(breaks = sort(emo_order), labels = emo_lookup[emo_order])

在这里,我们只是用 ouremo_order来表示我们想要从 1 到 8 的整数的中断,然后我们用有序emo_lookup表中的感觉标记这个中断。


推荐阅读