【问题标题】:Group by one column, select row with minimum in one column for every pair of columns按一列分组,为每对列选择一列中最小的行
【发布时间】:2016-05-30 17:29:19
【问题描述】:

难以表达的问题。这是我想做的一个例子。我开始的一个例子:

set.seed(0)
dt <- data.table(dr1.d=rnorm(5), dr1.p=abs(rnorm(5, sd=0.08)),
                 dr2.d=rnorm(5), dr2.p=abs(rnorm(5, sd=0.08)),
                 dr3.d=rnorm(5), dr3.p=abs(rnorm(5, sd=0.08)),
                 dr4.d=rnorm(5), dr4.p=abs(rnorm(5, sd=0.08)),
                 sym = paste("sym", c(1,1,1,2,2)))
dt

      dr1.d        dr1.p      dr2.d      dr2.p       dr3.d       dr3.p      dr4.d      dr4.p   sym
1:  1.2629543 0.1231960034  0.7635935 0.03292087 -0.22426789 0.040288638 -0.2357066 0.09215294 sym 1
2: -0.3262334 0.0742853628 -0.7990092 0.02017788  0.37739565 0.086861549 -0.5428883 0.07937283 sym 1
3:  1.3297993 0.0235776357 -1.1476570 0.07135369  0.13333636 0.055276307 -0.4333103 0.03436105 sym 1
4:  1.2724293 0.0004613738 -0.2894616 0.03485466  0.80418951 0.102767948 -0.6494716 0.09906433 sym 2
5:  0.4146414 0.1923722711 -0.2992151 0.09900307 -0.05710677 0.003738094  0.7267507 0.02234770 sym 2

对于共享药物的所有列对(例如“dr1”),我想按“sym”对行进行分组,然后选择每个组中 p 值最小的行(以“.p”结尾)。上述data.table的最终结果是这样的:

       dr1.d        dr1.p      dr2.d      dr2.p       dr3.d       dr3.p      dr4.d      dr4.p   sym
1:  1.3297993 0.0235776357  -0.7990092 0.02017788 -0.22426789 0.040288638 -0.4333103 0.03436105 sym 1
2:  1.2724293 0.0004613738  -0.2894616 0.03485466 -0.05710677 0.003738094  0.7267507 0.02234770 sym 2

我已尝试使用 .SD 和 lapply 来完成此操作,但我无法理解它。谢谢!

【问题讨论】:

    标签: r data.table


    【解决方案1】:

    了解data.table 最重要(也是最强大)的一点是,只要j 返回一个列表,列表中的每个元素都将成为结果中的一列。

    有了这些知识和一些基本的 R 乐趣,我们可以通过以下方式直接得到这个结果:

    # I'm on v1.9.7, see https://github.com/Rdatatable/data.table/wiki/Installation
    cols1 = grep("d$", names(dt), value=TRUE)
    cols2 = grep("p$", names(dt), value=TRUE)
    dt[, Map(`[`, mget(c(cols1,cols2)), lapply(mget(cols2), which.min)), by=sym]
    #      sym    dr1.d      dr2.d       dr3.d      dr4.d        dr1.p      dr2.p
    # 1: sym 1 1.329799 -0.7990092 -0.22426789 -0.4333103 0.0235776357 0.02017788
    # 2: sym 2 1.272429 -0.2894616 -0.05710677  0.7267507 0.0004613738 0.03485466
    #          dr3.p      dr4.p
    # 1: 0.040288638 0.03436105
    # 2: 0.003738094 0.02234770
    

    请参阅vignettes 了解更多信息。

    【讨论】:

      【解决方案2】:

      这是一种一体式方法,但您可能希望将其拆分为单独的步骤以提高可读性:

      dcast(melt(dt, measure = patterns("\\.p$", "\\.d$"), id.vars = "sym", 
        value.name = c("p", "d"))[, .SD[which.min(p)], by = list(sym, variable)], 
        sym ~ variable, value.var = c("p", "d"))
      #     sym          p_1        p_2         p_3        p_4      d_1        d_2         d_3        d_4
      #1: sym 1 0.0235776357 0.02017788 0.040288638 0.03436105 1.329799 -0.7990092 -0.22426789 -0.4333103
      #2: sym 2 0.0004613738 0.03485466 0.003738094 0.02234770 1.272429 -0.2894616 -0.05710677  0.7267507
      

      本质上是先通过两种模式融合,然后通过最小 p 值进行子集化,然后再转换回宽格式。

      【讨论】:

        【解决方案3】:

        通过一些熔化和铸造,这相当简单

        library(data.table)
        
        set.seed(0)
        dt <- data.table(dr1.d=rnorm(5), dr1.p=abs(rnorm(5, sd=0.08)),
                         dr2.d=rnorm(5), dr2.p=abs(rnorm(5, sd=0.08)),
                         dr3.d=rnorm(5), dr3.p=abs(rnorm(5, sd=0.08)),
                         dr4.d=rnorm(5), dr4.p=abs(rnorm(5, sd=0.08)),
                         sym = paste("sym", c(1,1,1,2,2)))
        
        
        dt[, rowid := .I] #add a row identifier
        dt <- melt(dt, id.vars = c("sym", "rowid"), variable.factor = F)
        
        dt[, c("col","val") := tstrsplit(variable, "." , fixed = T)] #split the column so we can group
        dt[, variable := NULL] #small cleanup
        
        
        dt <- dcast(dt, sym + rowid + col ~ val)
        dt <- dt[, .SD[which.min(p)], by = .(sym,col)] #select min row
        
        dt[, rowid := NULL] #cleanup
        
        dt <- dcast(melt(dt, id.vars = c("sym","col")), sym ~ col + variable)
        dt
                 sym    dr1_d        dr1_p      dr2_d      dr2_p       dr3_d       dr3_p      dr4_d      dr4_p
        1: sym 1 1.329799 0.0235776357 -0.7990092 0.02017788 -0.22426789 0.040288638 -0.4333103 0.03436105
        2: sym 2 1.272429 0.0004613738 -0.2894616 0.03485466 -0.05710677 0.003738094  0.7267507 0.02234770
        

        【讨论】:

          猜你喜欢
          • 2017-01-22
          • 2013-06-28
          • 2019-02-18
          • 2020-10-01
          • 1970-01-01
          • 1970-01-01
          • 2015-03-27
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多