bdecker
bdecker

Reputation: 23

Problems creating diverging stacked bar plots in R using Likert package

Using the Likert package in R, I am attempting to create diverging stacked bar plots to compare responses on survey items in which respondents rated each item based on two scales: Importance and Effectiveness (1 to 5, with a "Cannot Judge" option on each). For each item, I am centering the plot on the "3" category, with the percentage of 4 and 5 responses at the far right of the plot, and the percentage of responses below 3 on the far left. I attempted to include an example, but am a newbie and the terms of service do not allow me to do so.

My R code works fine when there are more than two levels. However, I experience issues when there are fewer than 3 levels.

Here is a minimal example:

Importance <- c(4,5,5,5,4,4)
Effectiveness <- c(5,4,4,4,5,5)
df <- data.frame(Importance,Effectiveness)
df

levels = c("Cannot Judge", "1", "2", "3", "4", "5")

df$Importance <- recode(df$Importance, from=c(0,1,2,3,4,5), to=c("Cannot Judge", "1", "2", "3", "4", "5"))
df$Importance <- as.factor(df$Importance)
df$Importance <- factor(df$Importance, levels=c("Cannot Judge", "1", "2", "3", "4", "5"), ordered=TRUE)
df$Effectiveness <- recode(df$Effectiveness, from=c(0,1,2,3,4,5), to=c("Cannot Judge", "1", "2", "3", "4", "5"))
df$Effectiveness <- as.factor(df$Effectiveness)
df$Effectiveness <- factor(df$Effectiveness, levels=c("Cannot Judge", "1", "2", "3", "4", "5"), ordered=TRUE)

df2 <- likert(df)
plot(df2)

This results in the following error:

Error in matrix(value, n, p) : 
  'data' must be of a vector type, was 'NULL'

The issue seems to be when I call the likert() command on the data.frame, after I have recoded the numeric data into factors. If I do not recode into factors, and just apply likert() to the raw data, the plot is produced, but it is automatically centered between 4 and 5 (in this dataset), which is not what I need.

I recognize that it would be better for the factors to be "Very Important", "Important", "Very Effective", "Effective", etc. However, because the two scales are different, I do not know another way to compare the two scales without maintaining the 1-5 scheme.

Why am I getting the

Error in matrix(value, n, p) : 
      'data' must be of a vector type, was 'NULL'?

And how can I adjust my code to make it work with two levels?

Thanks in advance.

Upvotes: 2

Views: 1671

Answers (2)

William Doane
William Doane

Reputation: 1476

Using your original data.frame, here's an algorithmic way to remove the left or right hand stacked bars layers when there's a completely missing value from the set of questions plotted...

Importance <- c(4,5,5,5,4,4)
Effectiveness <- c(5,4,4,4,5,5)
df <- data.frame(Importance,Effectiveness)
df

levels = c("Cannot Judge", "1", "2", "3", "4", "5")

df$Importance <- recode(df$Importance, from=c(0,1,2,3,4,5), to=c("Cannot Judge", "1", "2", "3", "4", "5"))
df$Importance <- as.factor(df$Importance)
df$Importance <- factor(df$Importance, levels=c("Cannot Judge", "1", "2", "3", "4", "5"), ordered=TRUE)
df$Effectiveness <- recode(df$Effectiveness, from=c(0,1,2,3,4,5), to=c("Cannot Judge", "1", "2", "3", "4", "5"))
df$Effectiveness <- as.factor(df$Effectiveness)
df$Effectiveness <- factor(df$Effectiveness, levels=c("Cannot Judge", "1", "2", "3", "4", "5"), ordered=TRUE)

df.likert <- likert(df)   

# This is the proposed fix
LHS <- 2 # layer number for SD D or equiv
RHS <- 3 # layer number for A SA or equiv
pp <- plot(df.likert)
if (sum(is.na(pp$layers[[LHS]]$data$Item)) > 0) pp$layers <- pp$layers[-LHS]
if (sum(is.na(pp$layers[[RHS]]$data$Item)) > 0) pp$layers <- pp$layers[-RHS]
pp

Upvotes: 0

MrFlick
MrFlick

Reputation: 206596

You get this error because you have no "low result" values. The likert.bar.plot function uses ggplot and it creates a layer for both the positive and negative responses, however, it does not check to see if there are any observations in these groups first. This when it adds a layers that's empty, you get the error message above.

The easiest way I found to eliminate the error and raw the plot was to remove the bad layer manually. You can do this with

df2 <- likert(df)
pp <- plot(df2)
pp$layers <- pp$layers[-2]

(At least in this case it was layer 2; if you set other options that may be different so you might have to try other values)

likert bar plot

Upvotes: 3

Related Questions