【问题标题】:Is there a way to make 2-way tables with different pairs of variable in R?有没有办法在 R 中制作具有不同变量对的二维表?
【发布时间】:2021-11-11 01:42:50
【问题描述】:

我正在清理算术测试的数据。

有些测试项目是多项选择题,学生选择其中一项(例如a)b)c))。

在数据集中,我通过将项目转换为二进制变量来创建新变量。 例如,如果正确答案是 a) 对于 Item1,我通过重新编码 a) = 1otherwise = 0 制作了 newItem_1NA 保持原样)。

我想通过表格原始变量和新变量来仔细检查重新编码是否成功完成。只做这一对(在本例中为Item1newItem_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):
-------------------
项目 1 1 0 不适用
###
b # # #
c###
d # # #
不适用 # # #

项目 2 1 0 不适用
###
b # # #
c###
d # # #
.....
----------------------
我希望我的解释清楚。

【问题讨论】:

  • 亲爱的 Ronak,我编辑了我的原始帖子。请看一看。

标签: r loops for-loop crosstab


【解决方案1】:

如果有更多列,请相应地扩展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

【讨论】:

  • 非常感谢 Marek 的回答。我不知道across 函数。
  • accros 对名称以“Item”开头的所有列 (starts_with("Item")) 执行 fcheckanswer 函数。 .x参数是来自当前列的值的向量,cur_column ()参数是当前列的名称。
【解决方案2】:

您可以获取变量中的列名并使用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

【讨论】:

  • 非常感谢罗纳克。这正是我想要的。我有另一个问题。 Map(function(p, q) tabyl(df, .data[[p]], .data[[q]]), x, y)这段代码中的“.data”是什么意思?
  • .data 是一个 dplyr 术语。当我们将列名作为字符串传递时使用它。
  • 非常感谢。现在很清楚了。
【解决方案3】:

您是否有不想使用 base r 表函数的原因?看起来你会得到你想要的:

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

【讨论】:

  • 非常感谢塔尼亚。这对我帮助很大!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-01-05
  • 1970-01-01
  • 1970-01-01
  • 2022-01-22
  • 1970-01-01
  • 1970-01-01
  • 2017-12-24
相关资源
最近更新 更多