Visualizando respostas do Likert usando R ou SPSS

19

Tenho 82 respondentes em 2 grupos (43 no Grupo A e 39 no Grupo B) que completaram uma pesquisa com 65 perguntas do tipo Likert, cada uma variando de 1 a 5 (concordo totalmente - discordo totalmente). Portanto, tenho um quadro de dados com 66 colunas (1 para cada pergunta + 1 indicando alocação de grupo) e 82 linhas (1 para cada respondente).

Usando R ou SPSS, alguém conhece uma boa maneira de visualizar esses dados.

Eu preciso de algo assim: insira a descrição da imagem aqui
(de Jason Bryer )

Mas não consigo fazer com que a seção inicial do código funcione. Como alternativa, encontrei bons exemplos de como visualizar dados Likert de uma postagem anterior Validada Cruzada: Visualizando Dados de Resposta de Itens Likert, mas não existem guias ou instruções sobre como criar esses gráficos de contagem centralizada ou gráficos de barras empilhados usando R ou SPSS.

Adão
fonte
1
Oi Adam, para esclarecer mais, você estava querendo usar as visualizações para mostrar diferenças entre os grupos? Nesse caso, esse não é um método recomendado.
23312 Michelle
O pacote de Jason Bryer não funcionou para mim, mas acho que ele o atualizou e está funcionando lindamente agora. Também adicionei uma solicitação de recebimento com um recurso extra para armazenar nomes de colunas como atributos e grupos. Usando isso, sou capaz de visualizar facilmente um questionário Likert de 45 perguntas dividido em grupos, e até mesmo dividido com outra variável, se assim o desejar. (Eu imprimo usando o knitr, por isso acaba com muitas subparcelas em um site, não uma plotagem gigantesca). Fiz uma descrição detalhada aqui: reganmian.net/blog/2013/10/02/…
Stian Håklev 2/13/13 /
Apenas para sua informação, para aqueles que leem essas respostas no futuro, parece que alguns dos recursos e funcionalidades dos irutils em relação aos dados do likert foram movidos para o pacote do Likert R ( consulte o CRAN aqui ).
precisa
O link bryer.org/2011/visualizing-likert-items parece estar quebrado. Uma correção ou substituição seria bem-vinda.
Nick Cox
1
Esse tipo de pergunta - com forte foco em código específico - é menos bem-vindo em 2018 do que em 2012. Independentemente disso, algumas referências cruzadas para qualquer pessoa interessada por isso são stats.stackexchange.com/questions/56322/ … E stats.stackexchange.com/questions/148554/…
Nick Cox

Respostas:

30

Se você realmente deseja usar gráficos de barras empilhados com um número tão grande de itens, aqui estão duas soluções possíveis.

Usando irutils

Me deparei com este pacote há alguns meses.

A partir do commit 0573195c07 no Github , o código não funcionará com um grouping=argumento. Vamos para a sessão de depuração de sexta-feira.

Comece baixando uma versão compactada do Github. Você precisará hackear o R/likert.Rarquivo, especificamente as funções likerte plot.likert. Primeiro, in likert, cast()é usado, mas o reshapepacote nunca é carregado (embora exista uma import(reshape)instrução no NAMESPACEarquivo). Você pode carregar isso você mesmo com antecedência. Segundo, há uma instrução incorreta para buscar rótulos de itens, onde a iestá oscilando em torno da linha 175. Isso também deve ser corrigido, por exemplo, substituindo todas as ocorrências de likert$items[,i]por likert$items[,1]. Em seguida, você pode instalar o pacote da maneira que costumava fazer na sua máquina. No meu Mac, eu fiz

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

Em seguida, com R, tente o seguinte:

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)

Isso deve funcionar, mas a renderização visual será péssima por causa do alto número de itens. plot(likert(resp))Porém, ele funciona sem agrupar (por exemplo ).

insira a descrição da imagem aqui

Sugiro, portanto, reduzir seu conjunto de dados para subconjuntos menores de itens. Por exemplo, usando 12 itens,

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

Recebo um gráfico de barras empilhado 'legível'. Você provavelmente pode processá-los depois. (Esses são ggplot2objetos, mas você não poderá organizá-los em uma única página gridExtra::grid.arrange()devido a um problema de legibilidade!)

insira a descrição da imagem aqui

Solução alternativa

Gostaria de chamar sua atenção para outro pacote, HH , que permite plotar escalas Likert como gráficos de barras empilhadas divergentes. Poderíamos reutilizar o código acima, como mostrado abaixo:

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

mas isso vai complicar um pouco as coisas porque precisamos converter frequências em contagens, definir subconjuntos likert objeto produzido por irutils, desanexar pacote, etc. Então, vamos começar novamente com estatísticas novas (contagens):

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

insira a descrição da imagem aqui

Para usar uma variável de agrupamento, você precisará trabalhar com arrayvalores numéricos.

# 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="")

Isso produzirá dois painéis separados, mas cabe em uma única página.

insira a descrição da imagem aqui

Editar 2016-6-3

  1. A partir de agora likert está disponível como pacote separado.
  2. Você não precisa remodelar a biblioteca ou desconectar os irutils e remodelar
chl
fonte
O último enredo me lembra pirâmides populacionais. Deveríamos obter alguns dados reais para ver como eles funcionam "em estado selvagem", com alguns dados que não são tão organizados. Eu admito que eles são atraentes e bonitos.
Andy W
@ Andy Esse é o caso, de fato. Veja HH::as.pyramidLikert.
chl 23/03
1
+1, a biblioteca (HH) é definitivamente o caminho a percorrer. Mas algo tem de errado ido com o seu penúltimo lote na ordenação das concordam / discordam etc.
Peter Ellis
@ PeterEllis Sim, parece que as categorias de resposta estão na ordem errada, de fato. (A ordem dos rótulos foi perdida ao tabular os dados, e os nomes das tabelas são organizados de acordo com a ordem lexicográfica.) Para um hack rápido, podemos simplesmente substituir t(apply(resp, 2, table))por t(apply(resp, 2, table))[,levels(resp[,1])]. E +1 para você também!
chl 02/03
7

Comecei a escrever uma postagem no blog sobre a recriação de muitos gráficos na postagem que você mencionou ( Visualizando dados de resposta de itens do Likert ) no SPSS, portanto, suponho que essa seja uma boa motivação para finalizá-los.

Como observa Michelle, o fato de você ter grupos é uma nova reviravolta em comparação com as perguntas anteriores. E embora os grupos possam ser levados em consideração usando os gráficos de barras empilhados, na IMO, eles são muito mais facilmente incorporados ao exemplo de plotagem de pontos na postagem original de chl. Eu incluí o código SPSS para gerá-lo no final do post, basicamente implica saber como remodelar seus dados no formato apropriado para gerar o referido gráfico (anotação fornecida no código para, esperançosamente, esclarecer algumas dessas questões). Aqui, usei uma codificação redundante (cor e forma) para distinguir pontos provenientes dos dois grupos e os tornei semi-transparentes para que você possa saber quando eles se sobrepõem (outra opção seria evitar os pontos quando se sobrepõem).

Figura 1: Gráficos de pontos por grupo

Por que isso é melhor do que os gráficos de barras empilhadas? Os gráficos de barras empilhadas codificam as informações no comprimento das barras. Quando você tenta fazer comparações entre comprimentos de barras, na mesma categoria de eixo ou entre painéis, o empilhamento impede que as barras tenham uma escala comum. Por exemplo, forneci uma imagem na Figura 2 na qual duas barras são colocadas em um gráfico em que sua localização inicial é diferente, qual barra é a mais larga (ao longo do eixo horizontal)?

Figura 2: Barras sem uma escala comum

Compare isso com a plotagem da Figura 3 abaixo, na qual as duas barras (do mesmo comprimento) são plotadas do mesmo ponto inicial. Intencionalmente tornei a tarefa difícil, mas você deve saber qual é mais longo.

Figura 3: Barras com uma escala comum

Os gráficos de barras empilhadas estão essencialmente fazendo o que é exibido na Figura 2. Os gráficos de pontos podem ser considerados mais semelhantes ao que é exibido na Figura 3, basta substituir a barra por um ponto no final da barra.

Não vou dizer que não gere nenhum gráfico específico para análise exploratória de dados, mas sugiro evitar os gráficos de barras empilhadas ao usar tantas categorias. Os gráficos de pontos também não são uma panacéia, mas acredito que fazer comparações entre painéis com os gráficos de pontos é muito mais fácil do que nos gráficos de barras empilhados. Considere alguns dos conselhos que eu forneço no meu blog aqui para tabelas, tente ordenar e / ou separar os gráficos em categorias significativas e verifique se os itens que você gostaria de ver em conjunto estão mais próximos nos gráficos. Embora alguns dos métodos de plotagem possam ser bem dimensionados para muitas perguntas (os mapas de calor categóricos são um exemplo), sem classificar, ainda será difícil identificar quaisquer padrões significativos (além de óbvios outliers).

Uma observação sobre o uso do SPSS. O SPSS pode gerar qualquer um dos itens anteriores vinculados aos gráficos, embora freqüentemente envolva saber como moldar seus dados (o mesmo se aplica ao ggplot, mas as pessoas têm desenvolvido pacotes para essencialmente reformular sua configuração). Para entender como a linguagem GPL da SPSS funciona melhor, sugiro ler o livro de Hadley Wickham sobre ggplot2no Use R! Series. Ele descreve a gramática necessária para entender como a GPL do SPSS funciona e é uma leitura muito mais fácil do que o manual de programação da GPL que acompanha o SPSS! Se você tiver alguma dúvida sobre a geração de gráficos específicos no SPSS, seria melhor fazer uma pergunta para um gráfico (já falei o suficiente aqui!). Atualizarei esta resposta com um link, se algum dia eu conseguir postagem no blog replicando alguns dos outros gráficos. Para uma prova do conceito dos mapas de calor ou gráficos de flutuação, você pode ver outra publicação minha, Alguns exemplos de Corrgrams no SPSS .

Código SPSS usado para gerar a Figura 1

****************************************.
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.
****************************************.
Andy W
fonte
Forte vantagem de mim por discutir educadamente, mas de maneira penetrante, as deficiências dos gráficos de barras empilhadas, que são fáceis de entender em princípio, mas geralmente muito menos fáceis de decodificar na prática.
23618 Nick Cox
5

Bem, eu vim com o código antes de você esclarecer. Deveria ter esperado, mas achei que eu deveria publicá-lo para que qualquer pessoa que venha aqui possa reutilizar esse código.

Dados fictícios para visualização

# 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"

Código para mapa de calor

# 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) 

Este é basicamente um modelo para visualizar os itens do Likert em um mapa de calor do site de Jason Bryon.

RJ-
fonte
1
github.com/jbryer/irutils/blob/master/R/likert.R é a fonte dos gráficos de barras empilhados que você deseja.
RJ
Para esclarecer, não quero comparar entre grupos. Apenas para apresentar as respostas de ambos os grupos de maneira sofisticada. Esta é uma ótima resposta. Realmente aprecio isso. Obrigado.
Adam
3

O código do @ RJ produz um gráfico como este, que é realmente uma tabela com células sombreadas. É bastante ocupado e um pouco difícil de decifrar. Uma tabela simples sem sombreamento pode ser mais eficaz (e você também pode colocar os dados em uma ordem mais significativa).

insira a descrição da imagem aqui

É claro que depende da mensagem principal que você está tentando comunicar, mas acho que isso é mais simples e um pouco mais fácil de entender. Ele também tem as perguntas e respostas em uma ordem lógica (principalmente!).

    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()

insira a descrição da imagem aqui

Ben
fonte
Concordou que o gráfico parece ocupado. Seria útil, no entanto, se as perguntas forem agrupadas em algum tipo de ordem, por exemplo, o Q1 - 10 pergunta sobre uma determinada dimensão e assim por diante. À primeira vista, se as tendências são óbvias, as cores diriam.
RJ-