【问题标题】:Follow-up: Generalizing a data.frame subsetting function后续:泛化一个data.frame子集函数
【发布时间】:2021-10-04 15:20:30
【问题描述】:

我正在跟进this great answer。在that answer 中,foo 函数帮助用户了解其他两个选定列group&outcome)中的哪个唯一study 值是常量 变化。在这种情况下,可能有 4 种情况 (2^2):

  1. group 不变,但 outcome 变化。
  2. outcome 不变,但 group 变化。
  3. outcomegroup 都不同。
  4. outcomegroup 两者都没有变化。

下面的函数 foo2 用于为 study 提取满足上述 4 种可能性的行。

在这个后续中,我想知道我们是否可以通过添加一个... 参数来扩展foo2 函数,以便用户可以输入一个或多个var_col(例如,var1_col、var2_col、...),然后函数会提取可能的情况(number of variable^2 情况)?

例如,在我下面的数据中,我有 4 选定的列 (sample,group,outcome,control),因此 8 可能存在的情况可以通过以下方式从该数据中提取一个新功能。

我知道如果用户添加多个变量,number of variable^2 会迅速增加,因此我想将 foo2 函数扩展到更多变量。

h = "
   case sample group outcome control
1     1      1     1       1       1
2     1      2     1       1       1
3     1      1     2       1       1
4     1      2     2       1       1
5     1      1     1       2       1
6     1      2     1       2       1
7     1      1     2       2       1
8     1      2     2       2       1
9     2      1     1       1       1
10    2      1     2       1       1
11    2      1     1       2       1
12    2      1     2       2       1
13    3      1     1       1       1
14    3      2     1       1       1
15    3      1     1       2       1
16    3      2     1       2       1
17    4      1     1       1       1
18    4      2     1       1       1
19    4      1     2       1       1
20    4      2     2       1       1
21    5      1     1       1       1
22    5      1     2       1       1
23    6      1     1       1       1
24    6      1     2       1       1
25    7      1     1       1       1
26    7      2     1       1       1
27    8      1     1       1       1
28    9      1     1       1       1
29    9      2     1       1       1
30    9      1     2       1       1
31    9      2     2       1       1
32    9      1     1       2       1
33    9      2     1       2       1
34    9      1     2       2       1
35    9      2     2       2       1
36    9      1     1       1       2
37    9      2     1       1       2
38    9      1     2       1       2
39    9      2     2       1       2
40    9      1     1       2       2
41    9      2     1       2       2
42    9      1     2       2       2
43    9      2     2       2       2
44   10      1     1       1       1
45   10      1     2       1       1
46   10      1     1       2       1
47   10      1     2       2       1
48   10      1     1       1       2
49   10      1     2       1       2
50   10      1     1       2       2
51   10      1     2       2       2
52   11      1     1       1       1
53   11      2     1       1       1
54   11      1     1       2       1
55   11      2     1       2       1
56   11      1     1       1       2
57   11      2     1       1       2
58   11      1     1       2       2
59   11      2     1       2       2
60   12      1     1       1       1
61   12      2     1       1       1
62   12      1     2       1       1
63   12      2     2       1       1
64   12      1     1       1       2
65   12      2     1       1       2
66   12      1     2       1       2
67   12      2     2       1       2
68   13      1     1       1       1
69   13      1     2       1       1
70   13      1     1       1       2
71   13      1     2       1       2
72   14      1     1       1       1
73   14      1     2       1       1
74   14      1     1       1       2
75   14      1     2       1       2
76   15      1     1       1       1
77   15      2     1       1       1
78   15      1     1       1       2
79   15      2     1       1       2
80   16      1     1       1       1
81   16      1     1       1       2"
h = read.table(text=h,h=T)

foo2 <- function(dat, study_col, group_col, outcome_col) {

    dat %>%
           dplyr::select({{study_col}}, {{group_col}}, {{outcome_col}}) %>%
           dplyr::group_by({{study_col}}) %>%
          dplyr::mutate(grp = stringr::str_c(n_distinct({{group_col}}) == 1, 
              n_distinct({{outcome_col}}) == 1 ))   %>%
           dplyr::ungroup(.) %>%
           dplyr::group_split(grp, .keep = FALSE) }

【问题讨论】:

    标签: r dataframe function dplyr tidyverse


    【解决方案1】:

    如果我们想在末尾添加3个点,将其捕获为ensyms中的符号,然后将其转换为字符串(as_string),通过循环across这些列进行唯一的更改,创建一个逻辑条件使用n_distinct 并使用reduce 粘贴(str_c),同时粘贴其他列(也可以在单个across 中简化),然后在最后的“grp”列上使用group_split

    foo2 <- function(dat, study_col, group_col, outcome_col, ...) {
       
        dot_cols <- ensyms(...)
        str_cols <- purrr::map_chr(dot_cols, rlang::as_string)
    
        dat %>%
               dplyr::select({{study_col}}, {{group_col}}, {{outcome_col}}, !!! dot_cols) %>%
                dplyr::group_by({{study_col}}) %>%
                dplyr::mutate(grp = across(all_of(str_cols), ~ n_distinct(.) == 1) %>%
                       purrr::reduce(stringr::str_c, collapse=""),
                              grp =  stringr::str_c(n_distinct({{group_col}}) == 1, 
                    n_distinct({{outcome_col}}) == 1, grp)) %>%
                    dplyr::ungroup(.) %>%
                     dplyr::group_split(grp, .keep = FALSE)
               
                }
    

    -测试

    > out <- foo2(h, case, group, outcome, sample, control)
    > out
    <list_of<
      tbl_df<
        case   : integer
        group  : integer
        outcome: integer
        sample : integer
        control: integer
      >
    >[14]>
    [[1]]
    # A tibble: 16 x 5
        case group outcome sample control
       <int> <int>   <int>  <int>   <int>
     1     9     1       1      1       1
     2     9     1       1      2       1
     3     9     2       1      1       1
     4     9     2       1      2       1
     5     9     1       2      1       1
     6     9     1       2      2       1
     7     9     2       2      1       1
     8     9     2       2      2       1
     9     9     1       1      1       2
    10     9     1       1      2       2
    11     9     2       1      1       2
    12     9     2       1      2       2
    13     9     1       2      1       2
    14     9     1       2      2       2
    15     9     2       2      1       2
    16     9     2       2      2       2
    
    [[2]]
    # A tibble: 8 x 5
       case group outcome sample control
      <int> <int>   <int>  <int>   <int>
    1     1     1       1      1       1
    2     1     1       1      2       1
    3     1     2       1      1       1
    4     1     2       1      2       1
    5     1     1       2      1       1
    6     1     1       2      2       1
    7     1     2       2      1       1
    8     1     2       2      2       1
    
    [[3]]
    # A tibble: 8 x 5
       case group outcome sample control
      <int> <int>   <int>  <int>   <int>
    1    10     1       1      1       1
    2    10     2       1      1       1
    3    10     1       2      1       1
    4    10     2       2      1       1
    5    10     1       1      1       2
    6    10     2       1      1       2
    7    10     1       2      1       2
    8    10     2       2      1       2
    
    [[4]]
    # A tibble: 4 x 5
       case group outcome sample control
      <int> <int>   <int>  <int>   <int>
    1     2     1       1      1       1
    2     2     2       1      1       1
    3     2     1       2      1       1
    4     2     2       2      1       1
    
    [[5]]
    # A tibble: 8 x 5
       case group outcome sample control
      <int> <int>   <int>  <int>   <int>
    1    12     1       1      1       1
    2    12     1       1      2       1
    3    12     2       1      1       1
    4    12     2       1      2       1
    5    12     1       1      1       2
    6    12     1       1      2       2
    7    12     2       1      1       2
    8    12     2       1      2       2
    
    [[6]]
    # A tibble: 4 x 5
       case group outcome sample control
      <int> <int>   <int>  <int>   <int>
    1     4     1       1      1       1
    2     4     1       1      2       1
    3     4     2       1      1       1
    4     4     2       1      2       1
    
    [[7]]
    # A tibble: 8 x 5
       case group outcome sample control
      <int> <int>   <int>  <int>   <int>
    1    13     1       1      1       1
    2    13     2       1      1       1
    3    13     1       1      1       2
    4    13     2       1      1       2
    5    14     1       1      1       1
    6    14     2       1      1       1
    7    14     1       1      1       2
    8    14     2       1      1       2
    
    [[8]]
    # A tibble: 4 x 5
       case group outcome sample control
      <int> <int>   <int>  <int>   <int>
    1     5     1       1      1       1
    2     5     2       1      1       1
    3     6     1       1      1       1
    4     6     2       1      1       1
    
    [[9]]
    # A tibble: 8 x 5
       case group outcome sample control
      <int> <int>   <int>  <int>   <int>
    1    11     1       1      1       1
    2    11     1       1      2       1
    3    11     1       2      1       1
    4    11     1       2      2       1
    5    11     1       1      1       2
    6    11     1       1      2       2
    7    11     1       2      1       2
    8    11     1       2      2       2
    
    [[10]]
    # A tibble: 4 x 5
       case group outcome sample control
      <int> <int>   <int>  <int>   <int>
    1     3     1       1      1       1
    2     3     1       1      2       1
    3     3     1       2      1       1
    4     3     1       2      2       1
    
    [[11]]
    # A tibble: 4 x 5
       case group outcome sample control
      <int> <int>   <int>  <int>   <int>
    1    15     1       1      1       1
    2    15     1       1      2       1
    3    15     1       1      1       2
    4    15     1       1      2       2
    
    [[12]]
    # A tibble: 2 x 5
       case group outcome sample control
      <int> <int>   <int>  <int>   <int>
    1     7     1       1      1       1
    2     7     1       1      2       1
    
    [[13]]
    # A tibble: 2 x 5
       case group outcome sample control
      <int> <int>   <int>  <int>   <int>
    1    16     1       1      1       1
    2    16     1       1      1       2
    
    [[14]]
    # A tibble: 1 x 5
       case group outcome sample control
      <int> <int>   <int>  <int>   <int>
    1     8     1       1      1       1
    

    测试总行数

    > sum(map_dbl(out, nrow))
    [1] 81
    > nrow(h)
    [1] 81
    

    如果我们想删除一些参数

    foo2 <- function(dat, study_col, ...) {
       
        dot_cols <- ensyms(...)
        str_cols <- purrr::map_chr(dot_cols, rlang::as_string)
    
        dat %>%
               dplyr::select({{study_col}}, !!! dot_cols) %>%
                dplyr::group_by({{study_col}}) %>%
                dplyr::mutate(grp = across(all_of(str_cols), ~ n_distinct(.) == 1) %>%
                       purrr::reduce(stringr::str_c, collapse="")) %>%
                    dplyr::ungroup(.) %>%
                     dplyr::group_split(grp, .keep = FALSE)
               
                }
    

    -测试

    >  foo2(h, case, group, outcome, sample, control)
    <list_of<
      tbl_df<
        case   : integer
        group  : integer
        outcome: integer
        sample : integer
        control: integer
      >
    >[14]>
    [[1]]
    # A tibble: 16 x 5
        case group outcome sample control
       <int> <int>   <int>  <int>   <int>
     1     9     1       1      1       1
     2     9     1       1      2       1
     3     9     2       1      1       1
     4     9     2       1      2       1
     5     9     1       2      1       1
     6     9     1       2      2       1
     7     9     2       2      1       1
     8     9     2       2      2       1
     9     9     1       1      1       2
    10     9     1       1      2       2
    11     9     2       1      1       2
    12     9     2       1      2       2
    13     9     1       2      1       2
    14     9     1       2      2       2
    15     9     2       2      1       2
    16     9     2       2      2       2
    
    [[2]]
    # A tibble: 8 x 5
       case group outcome sample control
      <int> <int>   <int>  <int>   <int>
    1     1     1       1      1       1
    2     1     1       1      2       1
    3     1     2       1      1       1
    4     1     2       1      2       1
    5     1     1       2      1       1
    6     1     1       2      2       1
    7     1     2       2      1       1
    8     1     2       2      2       1
    
    [[3]]
    # A tibble: 8 x 5
       case group outcome sample control
      <int> <int>   <int>  <int>   <int>
    1    10     1       1      1       1
    2    10     2       1      1       1
    3    10     1       2      1       1
    4    10     2       2      1       1
    5    10     1       1      1       2
    6    10     2       1      1       2
    7    10     1       2      1       2
    8    10     2       2      1       2
    
    [[4]]
    # A tibble: 4 x 5
       case group outcome sample control
      <int> <int>   <int>  <int>   <int>
    1     2     1       1      1       1
    2     2     2       1      1       1
    3     2     1       2      1       1
    4     2     2       2      1       1
    
    [[5]]
    # A tibble: 8 x 5
       case group outcome sample control
      <int> <int>   <int>  <int>   <int>
    1    12     1       1      1       1
    2    12     1       1      2       1
    3    12     2       1      1       1
    4    12     2       1      2       1
    5    12     1       1      1       2
    6    12     1       1      2       2
    7    12     2       1      1       2
    8    12     2       1      2       2
    
    [[6]]
    # A tibble: 4 x 5
       case group outcome sample control
      <int> <int>   <int>  <int>   <int>
    1     4     1       1      1       1
    2     4     1       1      2       1
    3     4     2       1      1       1
    4     4     2       1      2       1
    
    [[7]]
    # A tibble: 8 x 5
       case group outcome sample control
      <int> <int>   <int>  <int>   <int>
    1    13     1       1      1       1
    2    13     2       1      1       1
    3    13     1       1      1       2
    4    13     2       1      1       2
    5    14     1       1      1       1
    6    14     2       1      1       1
    7    14     1       1      1       2
    8    14     2       1      1       2
    
    [[8]]
    # A tibble: 4 x 5
       case group outcome sample control
      <int> <int>   <int>  <int>   <int>
    1     5     1       1      1       1
    2     5     2       1      1       1
    3     6     1       1      1       1
    4     6     2       1      1       1
    
    [[9]]
    # A tibble: 8 x 5
       case group outcome sample control
      <int> <int>   <int>  <int>   <int>
    1    11     1       1      1       1
    2    11     1       1      2       1
    3    11     1       2      1       1
    4    11     1       2      2       1
    5    11     1       1      1       2
    6    11     1       1      2       2
    7    11     1       2      1       2
    8    11     1       2      2       2
    
    [[10]]
    # A tibble: 4 x 5
       case group outcome sample control
      <int> <int>   <int>  <int>   <int>
    1     3     1       1      1       1
    2     3     1       1      2       1
    3     3     1       2      1       1
    4     3     1       2      2       1
    
    [[11]]
    # A tibble: 4 x 5
       case group outcome sample control
      <int> <int>   <int>  <int>   <int>
    1    15     1       1      1       1
    2    15     1       1      2       1
    3    15     1       1      1       2
    4    15     1       1      2       2
    
    [[12]]
    # A tibble: 2 x 5
       case group outcome sample control
      <int> <int>   <int>  <int>   <int>
    1     7     1       1      1       1
    2     7     1       1      2       1
    
    [[13]]
    # A tibble: 2 x 5
       case group outcome sample control
      <int> <int>   <int>  <int>   <int>
    1    16     1       1      1       1
    2    16     1       1      1       2
    
    [[14]]
    # A tibble: 1 x 5
       case group outcome sample control
      <int> <int>   <int>  <int>   <int>
    1     8     1       1      1       1
    

    【讨论】:

    • 我也更新了帖子。你能检查一下这是否是预期的
    • @rnorouzian 与dplyr::select({{study_col}}, {{group_col}}, {{outcome_col}}, !!! dot_cols) 相同,其中dot_cols 是我们从... 捕获的唯一对象
    • @rnorouzian 是的,您也可以跳过这些内容,并使用其他 grp 创建删除那些变异。我在想你需要这个作为额外的东西
    • 您需要在这些列上单独执行n_distinct
    • 嗨,Arun,请确保您已经看到 the new question 您让我发帖。别着急。
    猜你喜欢
    • 2021-10-08
    • 2021-10-03
    • 2016-09-15
    • 1970-01-01
    • 1970-01-01
    • 2021-09-26
    • 2014-01-07
    • 1970-01-01
    • 2012-04-04
    相关资源
    最近更新 更多