R 또는 SPSS를 사용하여 Likert 응답 시각화


19

나는 2 그룹 (82 그룹 응답자 A 그룹에서 43 그룹 B 그룹에서 39)에 각각 1-5의 65 Likert 질문에 대한 설문 조사를 완료했습니다 (강하게 동의-동의하지 않음). 따라서 66 열 (각 질문에 대해 1 + 그룹 할당을 나타내는 1)과 82 행 (각 응답자에 대해 1)의 데이터 프레임이 있습니다.

R 또는 SPSS를 사용하면 누구나이 데이터를 시각화하는 좋은 방법을 알고 있습니다.

나는 이와 같은 것이 필요하다 : 여기에 이미지 설명을 입력하십시오
( Jason Bryer의 )

그러나 코드의 초기 섹션을 작동시킬 수는 없습니다. 또는 이전 Cross Validated 게시물의 Likert 데이터를 시각화하는 방법에 대한 좋은 예를 찾았습니다. Likert 항목 응답 데이터 시각화 이지만 R 또는 SPSS를 사용하여 이러한 중심 카운트 그래프 또는 누적 막대 차트를 만드는 방법에 대한 지침이나 지침은 없습니다.


1
안녕하세요, Adam은 더 명확하게하기 위해 시각화를 사용하여 그룹 간의 차이점을 보여 주려고하십니까? 그렇다면 권장되는 방법이 아닙니다.
Michelle

Jason Bryer의 패키지는 나를 위해 일하는 데 사용되지 않았지만 그가 업데이트했다고 생각하며 지금은 아름답게 작동하고 있습니다. 또한 열 이름을 속성 및 그룹으로 저장하는 추가 기능과 함께 풀 요청을 추가했습니다. 이것을 사용하여 45 질문 리 커트 설문지를 그룹으로 분할하고 원하는 경우 다른 변수에 대해서도 분할하여 쉽게 시각화 할 수 있습니다. (편직기를 사용하여 출력 했으므로 웹 사이트에서 거대한 플롯이 아닌 많은 하위 플롯으로 끝납니다). 여기에 대한 자세한 작성자을했다 : reganmian.net/blog/2013/10/02/...
스티 Håklev

참고로 미래에 이러한 답변을 읽는 사람들에게는 likert 데이터와 관련하여 irutils의 일부 기능이 Likert R 패키지 로 이동 한 것처럼 보입니다 ( 여기 CRAN 참조 ).
firefly2442

bryer.org/2011/visualizing-likert-items 링크가 끊어진 것으로 보입니다. 수정 또는 교체를 환영합니다.
Nick Cox

1
특정 코드에 중점을 둔 이러한 종류의 질문은 2012 년보다 2018 년에 덜 환영 받습니다. … 그리고 stats.stackexchange.com/questions/148554/…
Nick Cox

답변:


30

이렇게 많은 수의 항목이있는 누적 막 대형 차트를 실제로 사용하려는 경우 가능한 두 가지 솔루션이 있습니다.

사용 irutils

몇 달 전에이 패키지를 보았습니다.

Github 의 커밋 0573195c07 현재 코드는 grouping=인수 와 함께 작동하지 않습니다 . 금요일의 디버깅 세션으로 갑시다.

Github에서 압축 버전을 다운로드하여 시작하십시오. R/likert.R파일, 특히 likertplot.likert기능 을 해킹해야 합니다. 먼저,에 likert, cast()사용되지만 reshape(이 생길 비록 패키지는로드되지 않습니다 import(reshape)에서 명령 NAMESPACE파일). 미리로드 할 수 있습니다. A는 어디에 둘째, 항목 레이블을 가져 오기 위해 잘못된 명령 거기 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. 현재 asrt 는 별도의 패키지로 제공됩니다.
  2. 라이브러리를 재구성 하거나 irutils재구성을 분리 할 필요가 없습니다.

마지막 줄거리는 인구 피라미드를 생각 나게합니다. 우리는 그것들이 "야생적으로"작동하는 방식을보기 위해 실제 데이터를 얻어야하며, 일부 데이터는 질서 정연하지 않습니다. 나는 그들이 눈길을 끌고 예쁘다는 것을 인정할 것입니다.
앤디 W

@ 앤디 사실이다. 참조하십시오 HH::as.pyramidLikert.
chl

1
+1, 도서관 (HH)은 확실히가는 길입니다. 그러나 동의 / 동의 등의 순서로 두 번째 마지막 줄거리에 문제가 있습니다.
Peter Ellis

@ PeterEllis Yup, 실제로 응답 범주의 순서가 잘못된 것 같습니다. (라벨의 순서는 데이터를 표로 때 손실되었고, 테이블 이름은 사전 식 순서에 따라 정렬됩니다.) 빠른 해킹을 위해, 우리는 단지 대체 할 수 있습니다 t(apply(resp, 2, table))t(apply(resp, 2, table))[,levels(resp[,1])]. 그리고 당신에게도 +1!
chl

7

SPSS에서 언급 한 게시물 ( Likert Item Response Data 시각화 )에서 많은 차트를 다시 작성하는 방법에 대한 블로그 게시물을 작성하기 시작했으며 이것이 마무리에 좋은 동기가 될 것이라고 생각합니다.

Michelle이 지적한 것처럼 그룹이 있다는 사실은 이전 질문과 비교하여 새로운 변화입니다. 누적 막대 그래프를 사용하여 그룹을 고려할 수 있지만 IMO는 chl의 원래 게시물에있는 도트 플롯 예제에 훨씬 쉽게 통합됩니다. SPSS 코드를 포함하여 게시물 끝에 이것을 생성했습니다. 기본적으로 해당 플롯을 생성하기 위해 적절한 형식으로 데이터를 재구성하는 방법을 알아야합니다 (코드에 제공된 주석을 희망적으로 정리하십시오). 여기에서는 두 그룹에서 나오는 점을 구별하기 위해 중복 인코딩 (색상 및 모양)을 사용하고 점을 반투명하게 만들었습니다. 따라서 점이 겹치는 시점을 알 수 있습니다 (다른 옵션은 점이 겹칠 때 점을 피하는 것입니다).

그림 1 : 그룹 별 도트 플롯

누적 막 대형 차트보다 더 나은 이유는 무엇입니까? 누적 막대 차트는 막대 길이로 정보를 인코딩합니다. 동일한 축 범주 내에서 또는 패널간에 막대의 길이를 비교하려고하면 누적으로 막대의 공통 축척이 배제됩니다. 예를 들어, 그림 2에서 두 개의 막대가 시작 위치가 다른 플롯에 배치되고 가로 막대를 따라 어느 막대가 더 넓은가?

그림 2 : 공통 스케일이없는 바

동일한 길이의 두 막대가 동일한 시작점에서 플롯되는 아래 그림 3의 플롯과 비교하십시오. 나는 의도적으로 과제를 어렵게 만들었지 만 어느 쪽이 더 긴지 알 수 있어야합니다.

그림 3 : 공통 스케일이있는 막대

누적 막 대형 차트는 본질적으로 그림 2에 표시된 것을 수행합니다. 점 그림은 그림 3에 표시된 것과 더 유사하게 간주 될 수 있습니다. 막대 끝에 막대를 막대로 바꿉니다.

탐색 적 데이터 분석을 위해 특정 차트를 생성하지 않는다고 말하지는 않지만 너무 많은 범주를 사용할 때 누적 막대 차트를 피하는 것이 좋습니다. 도트 플롯도 만병 통치약은 아니지만 도트 플롯으로 패널을 비교하는 것이 누적 막대 차트보다 훨씬 쉽다고 생각합니다. 블로그 게시물에서 표에 대해 제공하는 조언 중 일부를 고려하고 , 차트를 의미있는 카테고리로 주문 및 / 또는 분리하려고 시도하고, 동시에 보려는 항목이 차트에서 서로 더 가깝게 있는지 확인하십시오. 일부 플로팅 방법은 많은 질문에 맞게 확장 될 수 있지만 (범주 형 히트 맵이 한 예입니다) 정렬하지 않으면 의미있는 패턴 (명확한 이상 값 제외)을 식별하기가 여전히 어려울 수 있습니다.

SPSS 사용에 대한 참고 사항. SPSS는 데이터를 구성하는 방법을 알고있는 경우가 많지만 차트에 연결된 이전의 차트를 생성 할 수 있습니다 (ggplot도 마찬가지이지만 사람들은 본질적으로 재구성을 수행하기 위해 패키지를 개발하고 있습니다). SPSS의 GPL 언어가 어떻게 더 잘 작동하는지 이해하려면 실제로 ggplot2 에 관한 Hadley Wickham의 책을 읽는 것이 좋습니다.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.
****************************************.

스택 바 차트의 단점을 정중하지만 관통 적으로 논의 해 주신 것에 대한 저의 장점은 원칙적으로 이해하기 쉽지만 실제로는 해독하기가 훨씬 쉽지 않습니다.
Nick Cox

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-

명확히하기 위해 그룹 간 비교하고 싶지 않습니다. 두 그룹의 반응을 정교한 방식으로 제시하기 만하면됩니다. 이것은 큰 반응입니다. 정말 감사합니다. 감사.
Adam

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-
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.