【问题标题】:How to write new column conditional on grouped rows in R?如何在 R 中以分组行为条件编写新列?
【发布时间】:2016-06-02 10:18:58
【问题描述】:

我有一个数据框,其中每个 Item 具有三个类别(a、b、c),并且记录了每个类别的数字 Answer(0 或 1) .我想根据 Answer 列中的行创建一个新列。这是我的数据框的样子:

Item     <- rep(c(1:3), each=3)
Option   <- rep(c('a','b','c'), times=3)
Answer   <- c(1,1,0,1,0,1,1,1,1)
df       <- data.frame(Item, Option, Answer)


  Item Option Answer
1    1      a      1
2    1      b      1
3    1      c      0
4    2      a      0
5    2      b      0
6    2      c      1
7    3      a      1
8    3      b      1
9    3      c      1

需要什么:当 Option 列中的三个类别为 1 时,New 列应该得到 1。在任何其他情况下,列应该有0. 想要的输出应该是这样的:

  Item Option Answer New
1    1      a      1   0
2    1      b      1   0
3    1      c      0   0
4    2      a      0   0
5    2      b      0   0
6    2      c      1   0
7    3      a      1   1
8    3      b      1   1
9    3      c      1   1

我试图在不使用循环的情况下实现这一点,但我卡住了,因为我不知道如何根据一组行而不是单个行来创建一个新列。我试过this solution,但如果行没有成对分组,它就不起作用。

你有什么建议吗?非常感谢!

【问题讨论】:

  • 对于每个“项目”使用相同数量的“选项”,您可以考虑将数据存储在像 xtabs(Answer ~ Item + Option, df) 这样的“矩阵”中(并且“答案”为 0/1,您可以将其存储为稀疏的“矩阵”)。然后,例如,您可以使用 colSums 来计算 "1"s

标签: r dplyr tidyr


【解决方案1】:

这应该可行:

df %>%
  group_by(Item)%>%
  mutate(New = as.numeric(all(as.logical(Answer))))

【讨论】:

  • 谢谢!但是当我运行这个命令时,它会创建一个新列,全为 0(即使是项目 3,它也应该是 1)并且它给了我一个警告:In all(Answer) : coercing argument of type 'double' to合乎逻辑的。知道出了什么问题吗?
  • 它利用了 R 将 TRUE 表示为 1FALSE 表示为 0 的事实,但依赖于对逻辑的强制。警告不会阻止它工作(警告不是错误),但如果你想避免它们,要么显式强制,即as.numeric(all(as.logical(Answer))),要么显式测试,即as.numeric(all(Answer == 1))。无论哪种方式,all 都需要逻辑值来评估。
  • @alistaire:谢谢!我可以通过将 Answer 转换为逻辑来摆脱警告,但仍然存在解决方案不起作用的情况,并且新列仅显示 0。
  • 对我来说,所有三个选项都使用您提供的数据产生正确的结果。
  • @SolLago 使用您给出的示例,这对我有用。你能提供一个不起作用的例子吗?
【解决方案2】:

使用data.table

DT <- data.table(Item, Option, Answer)
DT[, Index := as.numeric(all(as.logical(Answer))), by= Item]
DT

    Item Option Answer Index
1:    1      a      1     0
2:    1      b      1     0
3:    1      c      0     0
4:    2      a      1     0
5:    2      b      0     0
6:    2      c      1     0
7:    3      a      1     1
8:    3      b      1     1
9:    3      c      1     1

【讨论】:

    【解决方案3】:

    或者只使用base R

    df$Index <- with(df, +(ave(!!Answer, Item, FUN = all)))
    df$Index
    #[1] 0 0 0 0 0 0 1 1 1
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-11-30
      • 1970-01-01
      • 2022-09-23
      • 2023-03-27
      • 1970-01-01
      • 2023-03-23
      • 1970-01-01
      • 2020-01-19
      相关资源
      最近更新 更多