0

我需要清理使用李克特量表收集的数据。这意味着我的数据中的观察结果来自从序数尺度中选择一个选项的人,例如“在 1-5 的尺度上,其中 1 表示糟糕,5 表示美妙,你如何评价你对茄子的喜爱程度?

因此,一个典型的数据集看起来像

library(tibble)

set.seed(123)
df_a <- 
  tibble(name = c("clara", "john", "michelle", "dan", 'timothy', "cindy", "george", "monica", "david", "rebecca"),
       response = sample(1:5, 10, replace = TRUE))

   name     response
   <chr>       <int>
 1 clara           3
 2 john            3
 3 michelle        2
 4 dan             2
 5 timothy         3
 6 cindy           5
 7 george          4
 8 monica          1
 9 david           2
10 rebecca         3

我的任务是测试数据是否确实是likert scale,这意味着(1)值是整数,(2)如果我们总结唯一值,它们是连续的。

  1. 测试是否都是整数可以通过
all((df_a$response - round(df_a$response)) == 0) ## https://stackoverflow.com/a/10114038/6105259

[1] TRUE
  1. 测试唯一值是否是连续的[实际上我不知道该怎么做,但我的问题并没有到此结束]。

我真正的问题是,李克特量表可能有不同的变化,并且其他字符串可能会显示在数据中,从而增加噪音。

  • 有效的李克特量表可以跨越不同的范围,例如 1-5、0-3 或 1-10 等。

  • 很多时候会有额外的字符串,比如“无关”、“我不知道”、“我不这么认为”、“不适用于我”等等。我无法预料数据中会出现哪些额外的字符串(如果有的话)。

在这种情况下,我需要检测我的数据是否本质上可能来自“李克特量表”。

决定数据的标准李克特量表:

  1. 数值是整数。
  2. 当我们采用唯一值时,它们是连续的(在 return 的意义上。如果它已经返回sort(unique(df_a$response)),那么它将不符合“连续性”标准)1 2 3 4 51 3 4 5
  3. 范围内的最小值是0或者1
  4. 最大值为10
  5. 数字的噪声字符串(例如“我不知道”、“abcd34”、“不相关”)占数据的不到 50%

下面是 4 个示例来演示可能的数据类型以及在测试它们是否“likert”时我期望发生的情况 在
我用来模拟“噪声”字符串的示例stringi::stri_rand_strings中(例如,“我不知道”、“无关”以及我上面给出的其他示例)


示例 1 - 测试“islikert scale”应该返回TRUE

library(stringi)

set.seed(19)
val_begin <- sample(0:1, 1)
val_end <- sample(3:10, 1)
my_seq <- seq(from = val_begin, to = val_end)
additional_strings <- stri_rand_strings(n = 2, length = 5, pattern = "[A-Za-z0-9]")

vec_example_1 <- sample(c(my_seq, additional_strings), size = 100 , replace = TRUE) 
barplot(prop.table(table(vec_example_1)), main = "vec example 1)

vec_example_1

示例 2 —— 测试“islikert scale”应该返回FALSE

以下数据中,数字不连续

set.seed(19)
my_seq_2 <- sort(c(seq(0,4), seq(7, 9)))
additional_strings_2 <- stri_rand_strings(n = 2, length = 5, pattern = "[A-Za-z0-9]")
vec_example_2 <- sample(c(my_seq_2, additional_strings_2), size = 100 , replace = TRUE) 
barplot(prop.table(table(vec_example_2)), main = "vec example 2)

vec_example_2

示例 3——测试“islikert scale”应该返回FALSE

在以下数据中,“附加字符串”占数据的50%以上,数据的核心不太可能是李克特量表

set.seed(19)
vec_example_3 <- sample(c(rep(additional_strings, 70), sample(my_seq, 30, replace = T))) 
barplot(prop.table(table(vec_example_3)), main = "vec example 3")

vec_example_3

示例 4——测试“islikert scale”应该返回FALSE

只是随机数和字符串,没有理由相信这是一个李克特量表,即使它碰巧是唯一且连续的,但 1 -> 30 根本不可能是李克特量表。

set.seed(19)
vec_example_4 <- sample(c(1:30, additional_strings), 1000, replace = T) 
barplot(prop.table(table(vec_example_4)), main = "vec example 4")

vec_example_4


我在问什么

我认为一个完整的解决方案会很长,所以向这里的人询问可能太多了。因此,即使只是提示、一般方法或解决此问题的想法,我也会很高兴。

4

1 回答 1

1

您可以编写一个函数来识别向量是否遵循我们正在寻找的规则。

is_likert <- function(x) {
  only_numbers <- sort(as.numeric(unique(grep('^\\d+$', x, value = TRUE))))
  all_integers <- all(only_numbers %% 1 == 0)
  are_consecutive <- all(diff(only_numbers) == 1)
  ratio_of_numbers <- mean(grepl('^\\d+$', x))
  max_num <- max(only_numbers)
  min_num <- min(only_numbers)

  all_integers && are_consecutive && ratio_of_numbers > 0.5 && 
  max_num <= 10 && min_num <= 1
}

is_likert(vec_example_1)
#[1] TRUE
is_likert(vec_example_2)
#[1] FALSE
is_likert(vec_example_3)
#[1] FALSE
is_likert(vec_example_4)
#[1] FALSE

我希望变量名称足够清晰,以证明它们在做什么。

于 2021-01-21T07:37:12.087 回答