【问题标题】:dplyr filter and then mutate while retaining all datadplyr 过滤然后变异,同时保留所有数据
【发布时间】:2021-01-25 21:27:53
【问题描述】:

我有一个数据集,其中包含每个母婴“二元组”的 id。我想创建一个只使用来自婴儿变量的数据的新变量。使用 dplyr::filter 函数很简单。但是,使用过滤器意味着丢失了母数据。有没有办法过滤,然后变异,同时仍然保留所有数据?

例子:

require(tidyverse)

dataSet <- data.frame(dyad_id = c(1,1,1,1,2,2,2,2,3,3,3,3),
                      dyad = c("Mom","Mom","Inf","Inf","Mom","Mom","Inf","Inf","Mom","Mom","Inf","Inf"),
                      timepoint = c(1,2,1,2,1,2,1,2,1,2,1,2),
                      v1 = c(3,4,5,2,4,6,3,67,8,4,3,2),
                      v2 = c(6,8,3,4,5,6,1,3,4,5,6,7))

dataSet <- dataSet %>% 
dplyr::filter(dyad == "Inf") %>% 
  dplyr::mutate(v3 = v1 + v2)

当我运行它时,它会从数据集中删除所有母体数据:

> dataSet
  dyad_id dyad timepoint v1 v2 v3
1       1  Inf         1  5  3  8
2       1  Inf         2  2  4  6
3       2  Inf         1  3  1  4
4       2  Inf         2 67  3 70
5       3  Inf         1  3  6  9
6       3  Inf         2  2  7  9

期望的输出:

   dyad_id dyad timepoint v1 v2 v3
1        1  Mom         1  3  6 NA
2        1  Mom         2  4  8 NA
3        1  Inf         1  5  3 8
4        1  Inf         2  2  4 6
5        2  Mom         1  4  5 NA
6        2  Mom         2  6  6 NA
7        2  Inf         1  3  1 4
8        2  Inf         2 67  3 70
9        3  Mom         1  8  4 NA
10       3  Mom         2  4  5 NA
11       3  Inf         1  3  6 9
12       3  Inf         2  2  7 9

提前致谢!

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    看看 dplyr 中的 if_else 函数:

    require(tidyverse)
    
    dataSet <- data.frame(dyad_id = c(1,1,1,1,2,2,2,2,3,3,3,3),
                          dyad = c("Mom","Mom","Inf","Inf","Mom","Mom","Inf","Inf","Mom","Mom","Inf","Inf"),
                          timepoint = c(1,2,1,2,1,2,1,2,1,2,1,2),
                          v1 = c(3,4,5,2,4,6,3,67,8,4,3,2),
                          v2 = c(6,8,3,4,5,6,1,3,4,5,6,7))
    
    dataSet <- dataSet %>% 
      dplyr::mutate(v3 = if_else(dyad == "Inf",v1 + v2,0))
    
    
    > head(dataSet)
      dyad_id dyad timepoint v1 v2 v3
    1       1  Mom         1  3  6  0
    2       1  Mom         2  4  8  0
    3       1  Inf         1  5  3  8
    4       1  Inf         2  2  4  6
    5       2  Mom         1  4  5  0
    6       2  Mom         2  6  6  0
                    
    

    【讨论】:

    • 非常感谢。唯一的问题是我希望“Mom”v3 变量为 NA 而不是 0。这是我在 mutate 函数中将“0”更改为 NA 时得到的错误:错误:mutate() 输入问题v3。 x false 必须是双向量,而不是逻辑向量。 ℹ 输入v3if_else(dyad == "Inf", v1 + v2, NA)
    • 你可以保持为零,然后添加这一行 dataSet[dataSet$dyad=="Mom","v3"] = NA
    • 另外,Infant 不是变量,而是一组行(或观察值)。 “dyad”是变量
    【解决方案2】:

    我们可以使用case_when,默认情况下会返回NA

    library(dplyr)
    dataSet %>%
        mutate(v3 = case_when(dyad == 'Inf' ~ v1 + v2))
    

    -输出

    #    dyad_id dyad timepoint v1 v2 v3
    #1        1  Mom         1  3  6 NA
    #2        1  Mom         2  4  8 NA
    #3        1  Inf         1  5  3  8
    #4        1  Inf         2  2  4  6
    #5        2  Mom         1  4  5 NA
    #6        2  Mom         2  6  6 NA
    #7        2  Inf         1  3  1  4
    #8        2  Inf         2 67  3 70
    #9        3  Mom         1  8  4 NA
    #10       3  Mom         2  4  5 NA
    #11       3  Inf         1  3  6  9
    #12       3  Inf         2  2  7  9
    

    【讨论】:

      【解决方案3】:

      我知道在 {tidyverse} 问题上用 {data.table} 回答有些不悦,但我将把它留在这里,因为它在 data.table 中实现起来非常方便

      library(data.table)
      dataSet <- as.data.table(dataSet)
      
      dataSet[filter_column == 'filter_value', mutate_column := 'mutate_value']
      

      不满足过滤条件的每一行都会在 mutate_column 上分配一个 NA(或者如果该列已经存在,它将保持这些值不变)

      所以,在你的情况下:

      dataSet[dyad == 'Inf', v3 := v1 + v2]
      

      然后您可以立即返回管道 dplyr 函数,您的数据集将再次变成一个 tibble,不会留下 data.table 操作的足迹。

      【讨论】:

        猜你喜欢
        • 2018-03-21
        • 1970-01-01
        • 1970-01-01
        • 2015-11-10
        • 2018-01-07
        • 1970-01-01
        • 2021-11-19
        • 1970-01-01
        相关资源
        最近更新 更多