我正在清理算术测试的数据。
部分试题为多项选择题,由学生任选其一(如a)
、b)
或c)
)。
在数据集中,我通过将项目转换为二进制变量来创建新变量。例如,如果正确答案是a)
为Item1,我通过重新编码a) = 1
和otherwise = 0
来制作newItem_1
(NA
保持原样)。
我想再检查一下,如果重新编码是成功地完成表的原始和新的变量。只做这一对(在本例中是Item1
和newItem_1
)很容易,但由于我有很多这样的多项选择题,因此编写脚本逐个表每一对是不高效的。
这是我的问题:是否有任何方法可以使每对这些原始和新的变量的双向表?我试着用for循环来解决这个问题,并在网上寻找技巧,但到目前为止还没有找到解决方案。
我提取了下面数据框的一部分。
structure(list(ID = 1:20, gender = c("Male", "Male", "Male",
"Male", "Male", "Male", "Male", "Male", "Male", "Male", "Male",
"Male", "Male", "Male", "Male", "Female", "Female", "Female",
"Female", "Female"), Item1 = c("c", "c", "a", "a", NA, "c", "c",
"b", "b", "b", "c", "c", NA, "c", "a", "d", "c", "c", "c", "c"
), Item2 = c("d", "d", "d", "d", "d", "a", "a", "a", "a", "b",
"b", "c", "c", "c", "c", "d", NA, NA, "d", "d"), Item3 = c("b",
"d", NA, "a", NA, "d", "c", "c", NA, "d", "c", NA, NA, "c", "d",
"c", "d", "d", "d", "d"), new_Item1 = c(1L, 1L, 0L, 0L, NA, 1L,
1L, 0L, 0L, 0L, 1L, 1L, NA, 1L, 0L, 0L, 1L, 1L, 1L, 1L), new_Item2 = c(1L,
1L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, NA,
NA, 1L, 1L), new_Item3 = c(0L, 0L, NA, 0L, NA, 0L, 1L, 1L, NA,
0L, 1L, NA, NA, 1L, 0L, 1L, 0L, 0L, 0L, 0L)), class = "data.frame", row.names = c(NA,
-20L))
提前感谢。
顺
对于一对,我只需输入:库(门卫)tabyl (g3, Item1, new_Item1)我可以看到我的编码是正确的。但是在本例中,我想在Item1、2和3(以及更多)之间循环相同的表格。因此,我的预期输出将类似于(如果我使用tabyl):
-------------------
Item1 1 0 NA
a # # #
b # # #
c # # #
d # # #
NA # # #
Item2 1 0 NA
a # # #
b # # #
c # # #
d # # #
.....
----------------------
我希望我的解释是清楚的。
如果有更多列,则相应地扩展truanswer
表。其余部分保持不变。您只能使用accros
函数进行一次突变。
注:我假设您的数据在dforg
表中。
library(tidyverse)
df = dforg %>% as_tibble() %>% select(ID:Item3)
truanswer = tribble(
~col, ~answer,
"Item1", "a",
"Item2", "c",
"Item3", "b"
)
fcheckanswer = function(x, col)
ifelse(x==truanswer$answer[truanswer$col==col], 1, 0)
df %>% mutate(
across(starts_with("Item"), ~ fcheckanswer(.x, cur_column()), .names = "{.col}_1"))
输出# A tibble: 20 x 8
ID gender Item1 Item2 Item3 Item1_1 Item2_1 Item3_1
<int> <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl>
1 1 Male c d b 0 0 1
2 2 Male c d d 0 0 0
3 3 Male a d NA 1 0 NA
4 4 Male a d a 1 0 0
5 5 Male NA d NA NA 0 NA
6 6 Male c a d 0 0 0
7 7 Male c a c 0 0 0
8 8 Male b a c 0 0 0
9 9 Male b a NA 0 0 NA
10 10 Male b b d 0 0 0
11 11 Male c b c 0 0 0
12 12 Male c c NA 0 1 NA
13 13 Male NA c NA NA 1 NA
14 14 Male c c c 0 1 0
15 15 Male a c d 1 1 0
16 16 Female d d c 0 0 0
17 17 Female c NA d 0 NA 0
18 18 Female c NA d 0 NA 0
19 19 Female c d d 0 0 0
20 20 Female c d d 0 0 0
您可以在变量中获取列名,并使用Map
循环遍历每对列名并返回比较表。
library(janitor)
x <- grep('^Item\d+$', names(df), value = TRUE)
y <- grep('^new_Item\d+$', names(df), value = TRUE)
Map(function(p, q) tabyl(df, .data[[p]], .data[[q]]), x, y)
#$Item1
# Item1 0 1 NA_
# a 3 0 0
# b 3 0 0
# c 0 11 0
# d 1 0 0
# <NA> 0 0 2
#$Item2
# Item2 0 1 NA_
# a 4 0 0
# b 2 0 0
# c 4 0 0
# d 0 8 0
# <NA> 0 0 2
#$Item3
# Item3 0 1 NA_
# a 1 0 0
# b 1 0 0
# c 0 5 0
# d 8 0 0
# <NA> 0 0 5
是否有不想使用基本表函数的原因?看起来你会得到你想要的:
table(g3$Item1, g3$new_Item1, useNA="always")
其中g3是上面定义的数据框架。
如果您想以不同的方式定义循环对,我建议这样做:
x = "Item1"
table(g3[, colnames(g3)==x], g3[, colnames(g3)==paste0("new_",x)], useNA="always")
其中x是循环变量。你可以比较&;x&;与"new_x"这种方式无需手动配对表函数中的每一列。你只需要在循环中输入一个x的列表。
输出为:
0 1 <NA>
a 3 0 0
b 3 0 0
c 0 11 0
d 1 0 0
<NA> 0 0 2