【问题标题】:Using group_by and mutate in dplyr package to create new factor variable by id variable在 dplyr 包中使用 group_by 和 mutate 通过 id 变量创建新的因子变量
【发布时间】:2016-03-11 21:45:27
【问题描述】:

我有一个长格式的分层数据框,其中每一行代表关系,其中许多可以属于一个人。这是一个小型示例数据集的代码:

df <- data.frame(id = as.factor(c(1,1,1,2,2,3,4,4)),
             partner = c(1,2,3,1,2,1,1,2),
             kiss = as.factor(c("Yes", "No", "No", "No", "No", "Yes", "Yes", "No")))

  id partner kiss
1  1       1  Yes
2  1       2   No
3  1       3   No
4  2       1   No
5  2       2   No
6  3       1  Yes
7  4       1  Yes
8  4       2   No

我想在此数据集中创建一个新的因子变量,指示此人(由“id 变量”表示)是否从未亲吻过他们的任何“伴侣”。换句话说,如果这个人与他们的任何伴侣接吻,新变量将指示“是”——他们从未与任何伴侣接吻。我认为它应该是这样的:

  id partner kiss neverkiss
1  1       1  Yes        No
2  1       2   No        No
3  1       3   No        No
4  2       1   No       Yes
5  2       2   No       Yes
6  3       1  Yes        No
7  4       1  Yes        No
8  4       2   No        No

理想情况下,我想找到一种方法来创建此变量,而无需重塑数据集。我也更喜欢使用 dplyr 包。到目前为止,我已经考虑过使用这个包中的 group_by 和 mutate 函数来创建这个变量。但是,我不确定我可以使用哪些辅助函数来创建我的特定变量。我对 dplyr 软件包之外的其他想法持开放态度,但这对我来说将是一等奖。

【问题讨论】:

  • df %&gt;% group_by(id) %&gt;% mutate(neverkiss = {if (any(kiss == "Yes")) "No" else "Yes"})
  • 您可以考虑使用logical 列而不是YesNo。然后,它只是df %&gt;% group_by(id) %&gt;% mutate(neverkiss = all(kiss != "Yes"))

标签: r dplyr


【解决方案1】:

应该这样做

require(dplyr)

df <- data.frame(id = as.factor(c(1,1,1,2,2,3,4,4)),
             partner = c(1,2,3,1,2,1,1,2),
             kiss = as.factor(c("Yes", "No", "No", "No", "No", "Yes", "Yes", "No")))

df_new <- df %>% 
   group_by(id) %>% 
   mutate("neverkiss" = {if (any(kiss == "Yes")) "No" else "Yes"})

df_new

如果新列应包含您必须首先ungroup 的因素

df_new <- df %>% 
   group_by(id) %>% 
   mutate("neverkiss" = {if (any(kiss == "Yes")) "No" else "Yes"}) %>% 
   ungroup() %>% 
   mutate("neverkiss" = as.factor(neverkiss))

class(df_new$neverkiss)
[1] "factor"

原因是因素不能结合:

a <- as.factor(c("Yes", "Yes", "Yes"))
b <- as.factor(c("No", "No", "No")) 

c(a, b) # meaningless

由于分组仍然处于活动状态,mutate 基本上将向量 neverkiss 构建为每个 id(组)的向量组合,这导致向量只有一个级别(在本例中为“否”)。

【讨论】:

  • 如果条件长度为 1,我将使用 ifelse 而不是 ifelse。请参阅 ?ifelse 中的注释。
【解决方案2】:

我们也可以使用data.table

library(data.table)
setDT(df)[, neverkiss := if(any(kiss=="Yes")) "No" else "Yes" , id]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-18
    • 2020-07-05
    • 1970-01-01
    • 2021-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多