Hình dung các phản hồi Likert bằng R hoặc SPSS


19

Tôi có 82 người trả lời trong 2 nhóm (43 trong nhóm A và 39 trong nhóm B) đã hoàn thành một cuộc khảo sát với 65 câu hỏi Likert mỗi câu từ 1 - 5 (rất đồng ý - rất không đồng ý). Do đó, tôi có một khung dữ liệu với 66 cột (1 cho mỗi câu hỏi + 1 chỉ định phân bổ nhóm) và 82 hàng (1 cho mỗi người trả lời).

Sử dụng R hoặc SPSS có ai biết một cách hay để trực quan hóa dữ liệu này.

Tôi cần một cái gì đó như thế này: nhập mô tả hình ảnh ở đây
(từ Jason Bryer )

Nhưng tôi không thể có được phần mã ban đầu để làm việc. Ngoài ra, tôi đã tìm thấy các ví dụ thực sự tốt về cách trực quan hóa dữ liệu Likert từ bài đăng Xác thực chéo trước đó: Trực quan hóa dữ liệu phản hồi mục Likert nhưng không có hướng dẫn hoặc hướng dẫn nào về cách tạo các biểu đồ đếm trung tâm này hoặc xếp hàng barchart bằng R hoặc SPSS.


1
Xin chào Adam, để làm rõ hơn, bạn có muốn sử dụng các hình ảnh trực quan để thể hiện sự khác biệt giữa các nhóm không? Nếu vậy, đó không phải là một phương pháp được đề nghị.
Michelle

Gói của Jason Bryer không sử dụng để làm việc cho tôi, nhưng tôi nghĩ rằng anh ấy đã cập nhật nó và nó hoạt động rất tốt ngay bây giờ. Tôi cũng đã thêm một yêu cầu kéo với một tính năng bổ sung để lưu trữ tên cột làm thuộc tính và nhóm. Sử dụng điều này, tôi có thể dễ dàng hình dung ra một câu hỏi Likert 45 câu hỏi được chia thành các nhóm, thậm chí tách thành một biến khác nếu tôi chọn. (Tôi xuất ra bằng cách sử dụng đan, vì vậy nó kết thúc với rất nhiều lô phụ trên một trang web, không phải là một âm mưu khổng lồ). Tôi đã viết chi tiết tại đây: reganmian.net/blog/2013/10/02/ Khăn
Stian Håklev

Chỉ cần FYI, đối với những bạn đọc những câu trả lời này trong tương lai, có vẻ như một số tính năng và chức năng của irutils liên quan đến dữ liệu Likeert đã được chuyển vào gói Likert R ( xem CRAN tại đây ).
firefly2442

Liên kết bowder.org/2011/visualizing-likert-items dường như bị phá vỡ. Một sự điều chỉnh hoặc thay thế sẽ được hoan nghênh.
Nick Cox

1
Loại câu hỏi này - tập trung mạnh vào mã cụ thể - ít được chào đón vào năm 2018 so với năm 2012. Bất kể đó là gì, một số tài liệu tham khảo chéo cho bất kỳ ai quan tâm đến điều này là stats.stackexchange.com/questions/56322/ ...stats.stackexchange.com/questions/148554/...
Nick Cox

Câu trả lời:


30

Nếu bạn thực sự muốn sử dụng barcharts xếp chồng với số lượng lớn các mặt hàng như vậy, đây là hai giải pháp có thể.

Sử dụng irutils

Tôi đã đi qua gói này một vài tháng trước.

Kể từ khi cam kết 0573195c07 trên Github , mã sẽ không hoạt động với một grouping=đối số. Hãy đi đến phiên gỡ lỗi vào thứ Sáu.

Bắt đầu bằng cách tải xuống phiên bản nén từ Github. Bạn sẽ cần hack R/likert.Rtệp, cụ thể là likertvà các plot.likertchức năng. Đầu tiên, trong likert, cast()được sử dụng nhưng reshapegói không bao giờ được tải (mặc dù có một import(reshape)lệnh trong NAMESPACEtệp). Bạn có thể tải cái này trước. Thứ hai, có một hướng dẫn không chính xác để lấy các nhãn vật phẩm, trong đó một cái ilủng lẳng quanh dòng 175. Điều này cũng phải được sửa, ví dụ bằng cách thay thế tất cả các lần xuất hiện likert$items[,i]bằng likert$items[,1]. Sau đó, bạn có thể cài đặt gói theo cách bạn đã sử dụng để làm trên máy của mình. Trên máy Mac của tôi, tôi đã làm

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

Sau đó, với R, hãy thử như sau:

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)

Điều đó chỉ nên làm việc, nhưng kết xuất hình ảnh sẽ là khủng khiếp vì số lượng lớn các mặt hàng. Nó hoạt động mà không cần nhóm (ví dụ, plot(likert(resp))), mặc dù.

nhập mô tả hình ảnh ở đây

Do đó tôi sẽ đề nghị giảm tập dữ liệu của bạn xuống các tập hợp con nhỏ hơn của các mục. Ví dụ: sử dụng 12 mục,

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

Tôi nhận được một barchart xếp chồng 'có thể đọc được'. Bạn có thể có thể xử lý chúng sau đó. (Đó là những ggplot2đối tượng, nhưng bạn sẽ không thể sắp xếp chúng trên một trang gridExtra::grid.arrange()vì vấn đề dễ đọc!)

nhập mô tả hình ảnh ở đây

Giải pháp thay thế

Tôi muốn thu hút sự chú ý của bạn vào một gói khác, HH , cho phép vẽ các thang đo Likert như các barcharts xếp chồng lên nhau. Chúng ta có thể sử dụng lại đoạn mã trên như hình dưới đây:

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

nhưng điều đó sẽ làm phức tạp mọi thứ một chút vì chúng ta cần chuyển đổi tần số thành số đếm, tập hợp con likertđối tượng được tạo ra irutils, tách gói, v.v. Vì vậy, hãy bắt đầu lại với số liệu thống kê (đếm) mới:

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

nhập mô tả hình ảnh ở đây

Để sử dụng biến nhóm, bạn sẽ cần làm việc với một arraygiá trị số.

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

Điều này sẽ tạo ra hai bảng riêng biệt, nhưng nó phù hợp trên một trang.

nhập mô tả hình ảnh ở đây

Chỉnh sửa 2016-6-3

  1. Cho đến bây giờ likeert có sẵn như là gói riêng biệt.
  2. Bạn không cần định hình lại thư viện hoặc tách cả irutilsđịnh hình lại

Cốt truyện cuối cùng làm tôi nhớ đến kim tự tháp dân số. Chúng ta nên có một số dữ liệu thực tế để xem cách chúng hoạt động "trong tự nhiên", với một số dữ liệu không theo thứ tự như vậy. Tôi sẽ thừa nhận họ là bắt mắt và mặc dù đẹp.
Andy W

@Andy Đó là trường hợp, thực sự. Xem HH::as.pyramidLikert.
chl

1
+1, thư viện (HH) chắc chắn là con đường để đi. Nhưng có điều gì đó không ổn với âm mưu cuối cùng thứ hai của bạn theo thứ tự đồng ý / không đồng ý, v.v.
Peter Ellis

@PeterEllis Yup, có vẻ như các danh mục phản hồi không đúng thứ tự. (Thứ tự nhãn bị mất khi lập bảng dữ liệu và tên bảng được sắp xếp theo thứ tự từ điển.) Để hack nhanh, chúng ta chỉ cần thay thế t(apply(resp, 2, table))bằng t(apply(resp, 2, table))[,levels(resp[,1])]. Và +1 cho bạn nữa!
chl

7

Tôi bắt đầu viết một bài đăng trên blog về việc tái tạo nhiều biểu đồ trong bài đăng mà bạn đề cập ( Trực quan hóa dữ liệu phản hồi mục Likert ) trong SPSS vì vậy tôi cho rằng đây sẽ là động lực tốt để hoàn thiện nó.

Như Michelle lưu ý, thực tế là bạn có các nhóm là một bước ngoặt mới so với các câu hỏi trước đó. Và trong khi các nhóm có thể được đưa vào tài khoản bằng cách sử dụng các biểu đồ thanh xếp chồng lên nhau, IMO, chúng dễ dàng được kết hợp hơn nhiều vào ví dụ về dấu chấm trong bài viết gốc của chl. Tôi đã bao gồm mã SPSS để tạo mã này ở cuối bài, về cơ bản, nó đòi hỏi phải biết cách định hình lại dữ liệu của bạn theo định dạng phù hợp để tạo ra âm mưu đã nói (chú thích được cung cấp trong mã để hy vọng xóa một số nội dung đó). Ở đây tôi đã sử dụng một số mã hóa dự phòng (màu sắc và hình dạng) để phân biệt các điểm đến từ hai nhóm và làm cho các điểm bán trong suốt để bạn có thể biết khi nào chúng trùng nhau (một tùy chọn khác sẽ là tránh các điểm khi chúng trùng nhau).

Hình 1: Các ô chấm theo nhóm

Tại sao điều này là tốt hơn so với các biểu đồ thanh xếp chồng lên nhau? Các biểu đồ thanh xếp chồng lên nhau mã hóa thông tin theo chiều dài của các thanh. Khi bạn cố gắng so sánh giữa các độ dài của các thanh, trong cùng một loại trục hoặc giữa các bảng, việc xếp chồng sẽ ngăn các thanh có tỷ lệ chung. Ví dụ, tôi đã cung cấp một hình ảnh trong Hình 2 trong đó hai thanh được đặt trong một ô trong đó vị trí bắt đầu của chúng khác nhau, thanh nào rộng hơn (dọc theo trục ngang)?

Hình 2: Các thanh không có tỷ lệ chung

So sánh điều đó với âm mưu trong Hình 3 bên dưới, trong đó hai thanh (có cùng độ dài) được vẽ từ cùng một điểm bắt đầu. Tôi đã cố tình làm cho nhiệm vụ khó khăn, nhưng bạn sẽ có thể biết cái nào dài hơn.

Hình 3: Các thanh có tỷ lệ chung

Biểu đồ thanh xếp chồng về cơ bản đang thực hiện những gì được hiển thị trong Hình 2. Các ô chấm có thể được coi là giống với những gì được hiển thị trong Hình 3, chỉ cần thay thế thanh bằng một dấu chấm ở cuối thanh.

Tôi sẽ không nói không tạo ra bất kỳ biểu đồ cụ thể nào để phân tích dữ liệu khám phá, nhưng tôi khuyên bạn nên tránh các biểu đồ thanh xếp chồng khi sử dụng quá nhiều danh mục. Các ô chấm cũng không phải là thuốc chữa bách bệnh, nhưng tôi tin rằng việc so sánh giữa các bảng với các ô chấm dễ dàng hơn nhiều so với các biểu đồ thanh xếp chồng lên nhau. Hãy xem xét một số lời khuyên tôi cung cấp trên bài đăng trên blog của mình ở đây cho các bảng, cố gắng sắp xếp và / hoặc tách các biểu đồ thành các danh mục có ý nghĩa và đảm bảo rằng các mục bạn muốn xem song song gần nhau hơn trong các biểu đồ. Mặc dù một số phương pháp vẽ biểu đồ có thể mở rộng tốt cho nhiều câu hỏi (bản đồ nhiệt phân loại là một ví dụ), nhưng không sắp xếp, sẽ vẫn khó xác định bất kỳ mẫu ý nghĩa nào (bên cạnh các ngoại lệ rõ ràng).

Một lưu ý khi sử dụng SPSS. SPSS có thể tạo bất kỳ biểu đồ nào được liên kết trước đó với biểu đồ, mặc dù nó thường đòi hỏi phải biết cách định hình dữ liệu của bạn (điều tương tự cũng đúng với ggplot, nhưng mọi người đã phát triển các gói để định hình lại cho bạn). Để hiểu cách ngôn ngữ GPL của SPSS hoạt động tốt hơn, tôi thực sự khuyên bạn nên đọc cuốn sách của Hadley Wickham trên ggplot2trong phần Sử dụng R! loạt. Nó đưa ra ngữ pháp cần thiết để hiểu GPL của SPSS hoạt động như thế nào và dễ đọc hơn nhiều so với hướng dẫn lập trình GPL đi kèm với SPSS! Nếu bạn có bất kỳ câu hỏi nào về việc tạo các biểu đồ cụ thể trong SPSS, tốt nhất nên hỏi một câu hỏi cho một biểu đồ (tôi đã nói đủ ở đây rồi!) Tôi sẽ cập nhật câu trả lời này bằng một liên kết mặc dù tôi có thể tìm cách tạo ra bài đăng trên blog sao chép một số biểu đồ khác. Để có bằng chứng về khái niệm bản đồ nhiệt hoặc sơ đồ biến động, bạn có thể xem một bài đăng trên blog khác của tôi, Một số ví dụ về Biểu đồ trong SPSS .

Mã SPSS được sử dụng để tạo Hình 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.
****************************************.

Điểm cộng mạnh mẽ từ tôi vì đã thảo luận một cách lịch sự nhưng sâu sắc về sự thiếu sót của các biểu đồ thanh xếp chồng lên nhau, dễ hiểu về nguyên tắc nhưng thường ít dễ giải mã hơn trong thực tế.
Nick Cox

5

Oh tốt, tôi đã đưa ra mã trước khi bạn làm rõ. Đáng lẽ phải đợi nhưng tôi nghĩ nên đăng nó lên để bất kỳ ai đến đây cũng có thể sử dụng lại mã này.

Dữ liệu giả để hình dung

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

Mã cho bản đồ nhiệt

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

Về cơ bản, đây là một mẫu để hiển thị các mục Likert trên bản đồ nhiệt từ trang web của Jason Bryon.


1
github.com/jbowder/irusils/blob/master/R/likert.R là nguồn cho các biểu đồ thanh xếp chồng bạn muốn.
RJ-

Để làm rõ, tôi không muốn so sánh giữa các nhóm. Chỉ cần trình bày cả hai nhóm trả lời một cách tinh vi. Đây là một phản ứng tuyệt vời. Thực sự đánh giá cao nó. Cảm ơn.
Adam

3

Mã của @ RJ tạo ra một âm mưu như thế này, đây thực sự là một bảng có các ô được tô bóng. Nó khá bận rộn và một chút khó khăn để giải mã. Một bảng đơn giản không có bóng có thể hiệu quả hơn (và bạn cũng có thể đặt dữ liệu theo thứ tự có ý nghĩa hơn).

nhập mô tả hình ảnh ở đây

Tất nhiên nó phụ thuộc vào thông điệp chính mà bạn đang cố gắng truyền đạt, nhưng tôi nghĩ rằng điều này đơn giản hơn và dễ hiểu hơn một chút. Nó cũng có các câu hỏi và câu trả lời theo thứ tự logic (chủ yếu!).

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

nhập mô tả hình ảnh ở đây


Đồng ý rằng biểu đồ có vẻ bận rộn. Tuy nhiên, sẽ rất hữu ích nếu các câu hỏi được nhóm theo một thứ tự nào đó, ví dụ Q1 - 10 hỏi về một chiều nhất định, v.v. Trong nháy mắt nếu các xu hướng là rõ ràng, màu sắc sẽ nói.
RJ-
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.