使用R或SPSS可视化Likert响应


19

我分为2组(A组为43个,B组为39个),有82位受访者完成了对65个李克特问题的调查,每个问题的范围为1-5(非常同意-非常不同意)。因此,我有一个具有66列(每个问题1个+ 1表示组分配)和82行(每个回答者1个)的数据框。

使用R或SPSS可以使任何人都知道可视化此数据的好方法。

我需要这样的东西:( 在此处输入图片说明
来自Jason Bryer

但是我无法使代码的最初部分起作用。另外,我找到了一个很好的示例,展示了如何从以前的交叉验证帖子中可视化Likert数据可视化Likert项目响应数据,但是没有有关如何使用R或SPSS创建这些居中计数图或堆积条形图的指南或说明。


1
嗨,亚当,您需要进一步说明一下,您是否想使用可视化效果显示两组之间的差异?如果是这样,则不建议这样做。
米歇尔(Michelle)2012年

杰森·布雷耶(Jason Bryer)的软件包对我没有用,但我认为他已对其进行了更新,并且目前运行良好。我还添加了带有附加功能的请求请求,以将列名称存储为属性和组。使用此工具,我可以轻松地将45个问题的李克特问卷分为几组可视化,如果我愿意的话,甚至可以将其分为另一个变量。(我使用knitr输出,因此最终在网站上出现了很多子图,而不是一个巨大的图)。我做了一个详细的书面记录在这里:reganmian.net/blog/2013/10/02/...
了StianHåklev

仅供参考,对于那些将来阅读这些答案的人来说,irutils有关Likert数据的某些功能似乎已经转移到Likert R包中请参见此处的CRAN)。
firefly2442 2013年

链接bryer.org/2011/visualizing-likert-items似乎已断开。更正或替换将是受欢迎的。
尼克·考克斯

1
此类问题-着重于特定代码-与2012年相比,在2018年受到的欢迎较少。无论如何,对此感兴趣的人的一些交叉引用是stats.stackexchange.com/questions/56322/ …stats.stackexchange.com/questions/148554/…–
尼克·考克斯

Answers:


30

如果您真的想将堆叠的条形图与大量物品一起使用,则有两种可能的解决方案。

使用 irutils

几个月前,我遇到了这个包裹。

Github上的 0573195c07提交开始,该代码将无法使用grouping=参数。让我们去参加周五的调试会议。

首先从Github下载压缩版本。您需要修改R/likert.R文件,特别是likertand plot.likert函数。首先,使用中的likertcast()但从reshape不加载程序包(尽管文件中有import(reshape)指令NAMESPACE)。您可以自己预先加载。其次,还有一个不正确的指令来获取物品的标签,其中一个i被替换所有出现的晃来晃去各地线175这已被固定为好,如likert$items[,i]likert$items[,1]。然后,您可以按照惯常的方式在计算机上安装软件包。在Mac上,我做了

% tar -czf irutils.tar.gz jbryer-irutils-0573195
% R CMD INSTALL irutils.tar.gz

然后,使用R,尝试以下操作:

library(irutils)
library(reshape)

# Simulate some data (82 respondents x 66 items)
resp <- data.frame(replicate(66, sample(1:5, 82, replace=TRUE)))
resp <- data.frame(lapply(resp, factor, ordered=TRUE, 
                          levels=1:5, 
                          labels=c("Strongly disagree","Disagree",
                                   "Neutral","Agree","Strongly Agree")))
grp <- gl(2, 82/2, labels=LETTERS[1:2]) # say equal group size for simplicity

# Summarize responses by group
resp.likert <- likert(resp, grouping=grp)

那应该就可以了,但是由于项目数量很大,视觉渲染效果会很糟糕。但是,它无需分组(例如plot(likert(resp)))即可工作。

在此处输入图片说明

因此,我建议将您的数据集减少为较小的项子集。例如,使用12个项目,

plot(likert(resp[,1:12], grouping=grp))

我得到了一个“可读”的堆叠条形图。您可能以后可以处理它们。(这些是ggplot2对象,但是gridExtra::grid.arrange()由于可读性问题,您将无法将它们排列在单个页面上!)

在此处输入图片说明

替代解决方案

我想在另一个包HH上引起您的注意,该包允许将李克特量表绘制为发散的堆叠条形图。我们可以重用上面的代码,如下所示:

resp.likert <- likert(resp)
detach(package:irutils)
library(HH)
plot.likert(resp.likert$results[,-6]*82/100, main="")

但这会使事情复杂化,因为我们需要将频率转换为计数,likert将由产生的对象进行子集化irutils,分离包装等。因此,让我们从新的(计数)统计数据开始:

plot.likert(t(apply(resp, 2, table)), main="", as.percent=TRUE,
            rightAxisLabels=NULL, rightAxis=NULL, ylab.right="", 
            positive.order=TRUE)

在此处输入图片说明

要使用分组变量,您需要使用array数值。

# compute responses frequencies separately by grp
resp.array <- array(NA, dim=c(66, 5, 2))
resp.array[,,1] <- t(apply(subset(resp, grp=="A"), 2, table))
resp.array[,,2] <- t(apply(subset(resp, grp=="B"), 2, table))
dimnames(resp.array) <- list(NULL, NULL, group=levels(grp))
plot.likert(resp.array, layout=c(2,1), main="")

这将产生两个单独的面板,但可放在单个页面上。

在此处输入图片说明

编辑2016-6-3

  1. 截至目前,likert可以单独购买。
  2. 您不需要重塑库或分离irutils重塑

最后的情节让我想起了人口金字塔。我们应该获得一些真实数据,以查看它们在“野外”如何工作,而某些数据却不是那么有序。我承认他们虽然引人注目而且漂亮。
安迪W

@Andy确实是这样。请参阅HH::as.pyramidLikert
chl 2012年

1
+1,图书馆(HH)绝对是必经之路。可是,我已经错在同意排序的倒数第二个情节/不同意等等
彼得·埃利斯

@PeterEllis是的,看起来响应类别的顺序确实错误。(标签的顺序制表数据时丢失了,和表名的排列如下字典顺序)。对于一个快速的黑客,我们只需更换t(apply(resp, 2, table))t(apply(resp, 2, table))[,levels(resp[,1])]。并且也向您+1!
chl

7

我开始写博客文章,内容涉及在SPSS中您提到的文章(可视化Likert项目响应数据)中的许多图表的重新创建,因此我认为这将是完成它的良好动力。

正如Michelle所指出的,与之前的问题相比,您拥有小组的事实是一个新的转折。尽管可以使用堆叠的条形图将组考虑在内,但在IMO的原始帖子中,将其更容易地并入点图示例中。我在帖子的末尾包含了生成此代码的SPSS代码,从本质上讲,它需要知道如何以适当的格式重塑数据以生成所述图(代码中提供了注释,希望可以清除其中的一部分)。在这里,我使用了一些冗余的编码(颜色和形状)来区分来自两个组的点,并使这些点为半透明的,以便您可以知道它们何时重叠(另一种选择是在它们重叠时避开这些点)。

图1:按组的点图

为什么这比堆积的条形图更好?堆叠的条形图将信息编码为条形的长度。当您尝试在相同轴类别内或面板之间对条形长度之间进行比较时,堆叠将使条形具有相同的比例。例如,我在图2中提供了一个图像,其中两个条形图放置在其开始位置不同的图中,哪个条形图更宽(沿水平轴)?

图2:没有通用比例尺的条形图

将其与下面的图3中的图进行比较,其中从相同的起点绘制了两个(相同长度的)条形图。我故意使这项任务变得困难,但是您应该能够分辨出哪一个更长。

图3:具有通用比例尺的条

堆叠的条形图实际上是在执行图2所示的操作。点图可以认为与图3所示的图形更相似,只需将条形图替换为条形图末端的点即可。

我不会说不要为探索性数据分析生成任何特定的图表,但我建议在使用太多类别时避免使用堆积的条形图。点图也不是万能药,但我相信使用点图在面板之间进行比较要比堆积条形图容易得多。考虑一下我在博客文章中为表格提供的一些建议,尝试将图表排序和/或分离为有意义的类别,并确保要串联查看的项目在图表中靠得很近。尽管某些绘图方法可以很好地解决许多问题(例如,分类热图),但如果不进行排序,则仍然很难识别出任何有意义的模式(除了明显的异常值以外)。

有关使用SPSS的说明。SPSS可以生成以前链接到图表的任何内容,尽管它经常需要知道如何塑造数据(ggplot也是一样,但是人们一直在开发软件包来本质上为您进行重塑)。为了理解SPSS的GPL语言如何更好地工作,我实际上建议阅读ggplot2上的Hadley Wickham的书在Use R中!系列。它列出了理解SPSS GPL的工作原理所必需的语法,并且比SPSS随附的GPL编程手册更容易阅读!如果您对在SPSS中生成特定图表有任何疑问,最好对一个图表问一个问题(我已经在这里说了足够多了!)我将通过链接更新此答案,尽管如果我能做的话,博客文章复制了其他一些图表。有关热图或波动图的概念证明,您可以参阅我的另一篇博客文章SPSS中的一些示例Corrgrams

用于生成图1的SPSS代码

****************************************.
input program. */making fake data similar to yours.
loop #i = 1 to 82.
compute case_num = #i.
end case.
end loop.
end file.
end input program.
execute.
dataset name likert.

*making number in groups.
compute group = 1.
if case_num > 43 group = 2.
value labels group
1 'A'
2 'B'.

*this makes 5 variables with categories between 0 and 5 (similar to Likert data with 5 categories plus missing data).
vector V(5).
do repeat V = V1 to V5.
compute V = TRUNC(RV.UNIFORM(0,6)).
end repeat.
execute.

value labels V1 to V5
0 'missing'
1 'very disagree'
2 'disagree'
3 'neutral'
4 'agree'
5 'very agree'.
formats case_num group V1 to V5 (F1.0).
*****************************************.

*Because I want to panel by variable, I am going to reshape my data so all of the "V" variables are in one column (stacking them in long format).
varstocases
/make V from V1 to V5
/index orig (V).

*I am going to plot the points, so I aggregate that information (you could aggregate total counts as well if you wanted to plot percentages.
DATASET DECLARE agg_lik.
AGGREGATE
  /OUTFILE='agg_lik'
  /BREAK=orig V group
  /count_lik=N.
dataset activate agg_lik.


*now the fun part, generating the chart.
*The X axis, dim(1) is the count of likert responses within each category for each original question.
*The Y axis, dim(2) is the likert responses, and the third axis is used to panel the observations by the original questions, dim(4) here beacause I want to panel
by rows instead of columns.
DATASET ACTIVATE agg_lik.
* Chart Builder.
GGRAPH
  /GRAPHDATASET NAME="graphdataset" VARIABLES=count_lik V group orig 
    MISSING=LISTWISE REPORTMISSING=NO
  /GRAPHSPEC SOURCE=INLINE.
BEGIN GPL
  SOURCE: s=userSource(id("graphdataset"))
  DATA: count_lik=col(source(s), name("count_lik"))
  DATA: V=col(source(s), name("V"), unit.category())
  DATA: group=col(source(s), name("group"), unit.category())
  DATA: orig=col(source(s), name("orig"), unit.category())
  GUIDE: axis(dim(1), label("Count"))
  GUIDE: axis(dim(2))
  GUIDE: axis(dim(4))
  GUIDE: legend(aesthetic(aesthetic.color.exterior), label("group"))
  GUIDE: text.title(label("Figure 1: Dot Plots by Group"))
  SCALE: cat(aesthetic(aesthetic.color.exterior), include("1", "2"))
  SCALE: cat(aesthetic(aesthetic.shape), map(("1", shape.circle), ("2", shape.square)))
  ELEMENT: point(position(count_lik*V*1*orig), color.exterior(group), color.interior(group), transparency.interior(transparency."0.7"), size(size."8px"), shape(group))
END GPL.
*The "SCALE: cat" statements map different shapes which I use to assign to the two groups in the plot, and I plot the interior of the points as partially transparent.
*With some post hoc editing you should be able to make the chart look like what I have in the stats post.
****************************************.

我礼貌而深刻地讨论了堆积条形图的不足之处,这些都是我的强项,原则上容易理解,但在实践中通常不那么容易理解。
尼克·考克斯

5

哦,好了,在您澄清之前,我想出了代码。应该等待,但以为我应该发布它,以便任何来这里的人都可以重用此代码。

虚拟数据可视化

# Response for http://stats.stackexchange.com/questions/25109/visualizing-likert-responses-using-r-or-spss
# Load libraries
library(reshape2)
library(ggplot2)

# Functions
CreateRowsColumns <- function(noofrows, noofcolumns) {
createcolumnnames <- paste("Q", 1:noofcolumns, sep ="")
df <- sapply(1:noofcolumns, function(i) assign(createcolumnnames[i], matrix(sample(1:5, noofrows, replace = TRUE))))
df <- sapply(1:noofcolumns, function(i) df[,i] <- as.factor(df[,i]))
colnames(df) <- createcolumnnames
return(df)}

# Generate dummy dataframe
LikertResponse <- CreateRowsColumns(82, 65)
LikertResponse[LikertResponse == 1] <- "Strongly agree"
LikertResponse[LikertResponse == 2] <- "Agree"
LikertResponse[LikertResponse == 3] <- "Neutral"
LikertResponse[LikertResponse == 4] <- "Disagree"
LikertResponse[LikertResponse == 5] <- "Strongly disagree"

热图代码

# Prepare data
LikertResponseSummary <- do.call(rbind, lapply(data.frame(LikertResponse), table))
LikertResponseSummaryPercent <- prop.table(LikertResponseSummary,1)

# Melt data
LikertResponseSummary <- melt(LikertResponseSummary)
LikertResponseSummaryPercent <- melt(LikertResponseSummaryPercent)

# Merge counts with proportions
LikertResponsePlotData <- merge(LikertResponseSummary, LikertResponseSummaryPercent, by = c("Var1","Var2"))

# Plot heatmap!
# Use the "geom_tile(aes(fill = value.y*100), colour = "white")" to control how you want the heatmap colours to map to.
ggplot(LikertResponsePlotData, aes(x = Var2, y = Var1)) +
    geom_tile(aes(fill = value.y*100), colour = "white") +
    scale_fill_gradient(low = "white", high = "steelblue", name = "% of Respondents") +
    scale_x_discrete(name = 'Response') +
    scale_y_discrete(name = 'Questions') +
    geom_text(aes(label = paste(format(round(value.y*100), width = 3), '% (', format(round(value.x), width = 3), ')')), size = 3) 

这基本上是可视化Jason Bryon网站上的热图上的Likert项目的模板。


1
github.com/jbryer/irutils/blob/master/R/likert.R是您想要的堆叠条形图的来源。
RJ- 2012年

为了澄清,我不想在组之间进行比较。只是为了以一种复杂的方式展示两个小组的回应。这是一个很好的回应。真的很感激。谢谢。
亚当

3

@RJ的代码生成这样的图,它实际上是带有阴影单元格的表。它相当忙,解密起来有些棘手。不带阴影的普通表可能会更有效(您也可以按更有意义的顺序放置数据)。

在此处输入图片说明

当然,这取决于您要传达的主要信息,但是我认为这更简单,也更容易理解。它还具有(大部分!)逻辑顺序的问题和答案。

    library(stringr)
    LikertResponseSummary$Var1num <- 
      as.numeric(str_extract(LikertResponseSummary$Var1, "[0-9]+"))
    LikertResponseSummary$Var2 <- 
      factor(LikertResponseSummary$Var2, 
      levels =  c("Strongly disagree", "Disagree", "Neutral", "Agree", "Strongly agree"))

ggplot(LikertResponseSummary, 
       aes(factor(Var1num), value, fill = factor(Var2))) + 
       geom_bar(position="fill") +
       scale_x_discrete(name = 'Question', breaks=LikertResponseSummary$Var1num,
                        labels=LikertResponseSummary$Var1) +
       scale_y_continuous(name = 'Proportion') +
       scale_fill_discrete(name = 'Response') +
       coord_flip()

在此处输入图片说明


同意图表看起来很忙。但是,如果将问题按某种顺序分组,例如Q1-10询问某个维度等等,这将是有用的。趋势一目了然,颜色就会显示出来。
RJ- 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.