问题描述
我需要清理使用李克特量表收集的数据。这意味着我的数据中的观察来自那些从序数表中选择一个选项的人,例如“在 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)如果我们总结了唯一值,它们是连续的。
- 测试是否都是整数可以通过
all((df_a$response - round(df_a$response)) == 0) ## https://stackoverflow.com/a/10114038/6105259
[1] TRUE
- 测试唯一值是否连续 [实际上我不知道该怎么做,但我的问题还不止于此]。
我真正的问题是李克特量表可能有不同的变化,并且其他字符串可能会显示在数据中,从而增加噪音。
-
有效的李克特量表可以跨越不同的范围,例如 1-5、0-3 或 1-10 等。
-
很多时候会出现附加字符串,例如“不相关”、“我不知道”、“我不这么认为”、“不适用于我”、等等。我无法预测数据中会出现哪些额外的字符串(如果有的话)。
在这种情况下,我需要检测我的数据是否本质上可能来自“李克特量表”。
决定数据的标准是李克特量表:
- 数值是整数。
- 当我们取唯一值时,它们是连续的(从某种意义上说,
sort(unique(df_a$response))
返回1 2 3 4 5
。如果它返回了1 3 4 5
,那么它将不符合“连续性”标准) - 范围内的最小值是
0
或1
- 最大值是
10
。 - 不是数字的噪声字符串(例如“我不知道”、“abcd34”、“不相关”)占数据的不到 50%
以下是 4 个示例,用于演示可能的数据类型以及我在测试它们是否“likert”时应该发生的情况
在示例中,我使用 stringi::stri_rand_strings
来模拟“噪音”字符串(例如,“我不知道”、“不相关”以及我上面给出的其他示例)
示例 1 -- 对“is Likert 量表”的测试应返回 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)
示例 2 -- 测试“is Likert 量表”应返回 FALSE
以下数据中,数字不连续
set.seed(19)
my_seq_2 <- sort(c(seq(0,4),seq(7,9)))
additional_strings_2 <- stri_rand_strings(n = 2,pattern = "[A-Za-z0-9]")
vec_example_2 <- sample(c(my_seq_2,additional_strings_2),replace = TRUE)
barplot(prop.table(table(vec_example_2)),main = "vec example 2)
示例 3 -- 对“is Likert 量表”的测试应返回 FALSE
以下数据中,“附加字符串”占数据的50%以上,数据的核心不太可能是likert scale
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")
示例 4 -- 测试“is Likert 量表”应返回 FALSE
只是随机数字和字符串,没有理由相信这是一个likert量表,即使它恰好是唯一且连续的,但1-> 30根本不可能是likert。
set.seed(19)
vec_example_4 <- sample(c(1:30,1000,replace = T)
barplot(prop.table(table(vec_example_4)),main = "vec example 4")
我在问什么
我认为一个完整的解决方案会很长,所以也许这里的人要求太多了。因此,即使只是提示、一般方法或如何解决此问题的想法,我也会很高兴。
解决方法
您可以编写一个函数来确定向量是否符合我们正在寻找的规则。
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
我希望变量名足够清楚,以展示它们在做什么。