【问题标题】:Dividing rows by rows using dplyr and tidyr使用 dplyr 和 tidyr 逐行划分行
【发布时间】:2020-11-27 03:29:17
【问题描述】:

我正在尝试使用 dplyr 处理(相当大的)数据集,我相信我的问题源于对“summarise_if”函数的使用不当。下面是一些代码来生成看起来像我的虚拟数据:

df <- data.frame(Block = c(1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4),
                 Treatment = c(rep("Control", 4), rep("CF", 4), rep("LR", 4)),
                 var1 = c(9, 12, 15, 16, 11, 9, 13, 11, 5, 11, 5, 11), 
                 var2 = c(0, 4, 9, 3, 6, 0, 0, 10, 15, 25, 0, 0))

我想按块和处理对数据进行分组,然后,对于每个变量(var1、var2、...),我想将每个块的“处理”值除以“控制”值。生成的数据框看起来像这样(我还没有为我的虚拟数据完成所有数学运算,所以我只是将示例公式放在每个单元格中应该计算的内容):

    Treatment    Block              var1              var2
    CF               1        CF/control        CF/control
    CF               2        CF/control        CF/control
    CF               3        CF/control        CF/control
    CF               4        CF/control        CF/control
    LR               1        LR/control        LR/control
    LR               2        LR/control        LR/control
    LR               3        LR/control        LR/control
    LR               4        LR/control        LR/control

一些值将是 NaN 或无穷大,因为我在某些处理中除以零,但这没关系。

我能够使用此代码一次为单个变量和处理生成我想要的:

df %>% 
  dplyr::group_by(Block) %>%
  dplyr::summarise(value = var1[Treatment=="CF"] / var1[Treatment=="Control"])

但是,由于有很多变量和处理方法,这变得乏味。但是,当我尝试对整个数据框执行此操作时,我会遇到各种错误。我最好的猜测是这样的:

df %>% 
  dplyr::group_by(Block, Treatment) %>%
  dplyr::summarise_if(is.numeric, value = .[Treatment=="CF"] / .[Treatment=="Control"])

这给了我“未找到对象'治疗'”的错误,并且仍然迫使我逐个治疗。

感谢任何帮助!

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    您可以使用以下内容:

    df %>% 
      dplyr::group_by(Block) %>%
      dplyr::summarise(across(where(is.numeric), 
              list(CF = ~.[Treatment=="CF"] / .[Treatment=="Control"], 
                   LR = ~.[Treatment=="LR"] / .[Treatment=="Control"]))) 
    
    
    #  Block var1_CF var1_LR var2_CF var2_LR
    #  <dbl>   <dbl>   <dbl>   <dbl>   <dbl>
    #1     1   1.22    0.556  Inf     Inf   
    #2     2   0.75    0.917    0       6.25
    #3     3   0.867   0.333    0       0   
    #4     4   0.688   0.688    3.33    0   
    

    如果您希望输出遵循与预期输出中显示的相同格式,您可以使用pivot_longer。

    df %>% 
      dplyr::group_by(Block) %>%
      dplyr::summarise(across(where(is.numeric), 
               list(CF = ~.[Treatment=="CF"] / .[Treatment=="Control"], 
                    LR = ~.[Treatment=="LR"] / .[Treatment=="Control"]))) %>%
      tidyr::pivot_longer(cols = -Block, 
                   names_to = c('.value', 'Treatment'), 
                   names_sep = '_')
    
    
    #  Block Treatment  var1   var2
    #  <dbl> <chr>     <dbl>  <dbl>
    #1     1 CF        1.22  Inf   
    #2     1 LR        0.556 Inf   
    #3     2 CF        0.75    0   
    #4     2 LR        0.917   6.25
    #5     3 CF        0.867   0   
    #6     3 LR        0.333   0   
    #7     4 CF        0.688   3.33
    #8     4 LR        0.688   0   
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-23
      • 2020-07-20
      • 1970-01-01
      • 2016-07-05
      • 2016-06-05
      • 2016-07-31
      相关资源
      最近更新 更多