【问题标题】:R Get minimum value in dataframe selecting rows on 2 columns [duplicate]R在2列上选择行的数据框中获取最小值[重复]
【发布时间】:2020-08-29 18:00:43
【问题描述】:

我有一个类似于我在下面简化的数据框。我想首先根据 X 列选择具有相同值的行,然后在该选择中根据 Y 列选择具有相同值的行。然后从该选择中,我想取最小值。我现在正在使用 forloop,但似乎必须有一种更简单的方法。谢谢!

set.seed(123)    
data<-data.frame(X=rep(letters[1:3], each=8),Y=rep(c(1,2)),Z=sample(1:100, 12))
data
   X Y  Z
1  a 1 76
2  a 1 22
3  a 2 32
4  a 2 23
5  b 1 14
6  b 1 40
7  b 2 39
8  b 2 35
9  c 1 15
10 c 1 13
11 c 2 21
12 c 2 42

期望的结果:

   X Y  Z
2  a 1 22
4  a 2 23
5  b 1 14
8  b 2 35
10 c 1 13
11 c 2 21

【问题讨论】:

    标签: r dataframe select multiple-columns min


    【解决方案1】:

    这是data.table 解决方案:

    library(data.table)
    data = data.table(data)
    data[, min(Z), by=c("X", "Y")]
    

    根据 OP 的评论进行编辑:

    如果我们排序的其中一列中有 NA 值,则会创建一个额外的行:

    data[2,2] <-NA
    data[, min(Z,na.rm = T), by=c("X", "Y")]
    
       X  Y V1
    1: a  1 31
    2: a NA 79
    3: a  2 14
    4: b  1 31
    5: b  2 14
    6: c  1 50
    7: c  2 25
    

    【讨论】:

    • 谢谢。将我的数据框更改为数据表有什么缺点吗?任何我应该考虑的...
    • 没有缺点。 data.table 仍然是 data.frame,这意味着它可以做 data.frame 可以做的所有事情,只是多了一些功能。 (如果我错了,任何人都可以纠正我)
    • NA 会被忽略吗?好像是这样的:)
    • 嗨,我用 NA 值编辑了答案。你是这个意思吗?
    • 对不起,我的意思是 V1 列中的 NA 值。它取最小值,忽略 NA。但我认为最初的代码是正确的
    【解决方案2】:
    library(tidyverse)
    data %>%
      group_by(X, Y) %>%
      summarise(Z = min(Z))
    

    会成功的!现在的另一个答案是data.table 方式,这是tidyverse。两者都是处理数据清理和操作的非常强大的方法 - 熟悉其中一种方法可能会有所帮助!

    【讨论】:

      【解决方案3】:

      base 中,您可以使用 aggregateZ 中获取最小值,按剩余列分组,例如:

      aggregate(Z~.,data,min)
      #  X Y  Z
      #1 a 1 31
      #2 b 1 31
      #3 c 1 50
      #4 a 2 14
      #5 b 2 14
      #6 c 2 25
      

      如果组中有NA

      data[2,2] <-NA
      

      忽略它:

      aggregate(Z~.,data,min)
      #  X Y  Z
      #1 a 1 31
      #2 b 1 31
      #3 c 1 50
      #4 a 2 14
      #5 b 2 14
      #6 c 2 25
      

      显示它:

      aggregate(data$Z, list(X=data$X, Y=addNA(data$Y)), min)
      #  X    Y  x
      #1 a    1 31
      #2 b    1 31
      #3 c    1 50
      #4 a    2 14
      #5 b    2 14
      #6 c    2 25
      #7 a <NA> 79
      

      【讨论】:

      • 优雅的答案。干得好。
      【解决方案4】:

      这段代码可以从多行拆分中受益,但它可以工作。在 Base-R 中

      do.call(rbind,
      lapply(unlist(lapply(split(data,data$X), function(x) split(x,x$Y)),recursive=F), function(y) y[y$Z==min(y$Z),])
      )
      
          X Y  Z
      a.1 a 1 31
      a.2 a 2 14
      b.1 b 1 31
      b.2 b 2 14
      c.1 c 1 50
      c.2 c 2 25
      

      【讨论】:

        猜你喜欢
        • 2019-12-23
        • 1970-01-01
        • 1970-01-01
        • 2020-09-22
        • 2019-09-03
        • 2017-12-29
        • 1970-01-01
        • 1970-01-01
        • 2022-12-20
        相关资源
        最近更新 更多