【问题标题】:How to find a minimum of two columns based on a condition?如何根据条件找到至少两列?
【发布时间】:2021-12-26 12:18:23
【问题描述】:

我在 R 中有一个这样的数据框

ID1    <- c(1,2,3,4,5,6,7,8,9)
Value1 <- c(2,3,5,2,5,8,17,3,5)
ID2 <- c(1,2,3,4,5,6,7,8,9)
Value2 <- c(4,6,3,5,8,1,2,8,10)

df <- as.data.frame(cbind(ID1,Value1,ID2,Value2))

现在我正在寻找 ID1 和 ID2 之和等于或小于 9 的 Value1 和 Value2 之和的最小值。因此,它应该显示 Value1 + Value2 组合的最小值(不需要ID1+ID2之和不超过9。

结果应该指向 Value1 中的 x 和 Value2 中的 y 的组合,它们一起是 ID1+ID2 为

提前致谢!

【问题讨论】:

  • 非常感谢您的快速回复!恐怕在我原来的帖子中犯了一个错误。我不需要基于行和的最小值,而是任何 Value1 + Value2 的组合的最小值,与行无关。因此,只要条件 ID1+ID2
  • 请编辑您的原始帖子,以反映这一点。
  • 我已经做过了,希望现在更清楚
  • 如果您可以将预期结果定义为模拟表或数据框也会很有帮助。
  • 不幸的是,我不知道 R 中的输出是什么样的。对我来说,将我指向 Value1 和 Value2 或 ID1 和 ID2 就足够了,其中所需的最小值在找到条件。

标签: r minimum


【解决方案1】:

一种可能性

library(dplyr)
goodrow <- filter(df, ID1 + ID2 <= 9) %>% mutate(sumval = Value1 + Value2) %>% filter(sumval == min(sumval))

如果我能很好地理解您的问题,请考虑使用交叉函数。这将计算 ID1 和 ID2 的所有组合

library(dplyr)

df <- as.data.frame(cbind(ID1,Value1))
df2 <- as.data.frame(cbind(ID2,Value2))
df_test <- crossing(df, df2)


goodrow <- filter(df_test, ID1 + ID2 <= 9) %>% mutate(sumval = Value1 + Value2) %>% filter(sumval == min(sumval))

【讨论】:

  • 这个方法可以编辑,让Value1+Value2的组合不需要在同一行吗?它不需要作为 rowSum,而是作为任何 Value1 + 任何 Value2 的独立总和,其中相应的 ID1+ID2 为
  • @Josh 为什么不直接取 ID1ID2 的全局最小值,彼此独立?
  • 可以说,Value1 + Value2 的值是两年的潜在费用,我可以添加一个有限的金额来减少费用。现在我需要找到这个总和的最佳分布(在上面的例子中=9,可以用于 ID1 和/或 ID2)以获得两年的最低费用。所以没有独立的。
  • @Josh 我刚刚编辑了它。希望它能回答你的问题。如果你需要在大数据集上做,代码不是很干净,但你可以试一试。
  • @FlavienPETIT 感谢您的回复!这几乎就是我想要的。原始数据帧是 4992 行,因此它足够小,可以使用 cross() 函数 - 产生约 2500 万行。我想知道如果我得到更大的数据框是否还有其他方法,但这是我现在需要的解决方案。谢谢。
【解决方案2】:

针对您的具体情况

which.min(rowSums(df[rowSums(df[,c("ID1","ID2")])<10,c("Value1","Value2")]))

【讨论】:

    【解决方案3】:

    您可以使用 SQL 查询通过 sqldf 包回答问题

    library(sqldf)
    #> Loading required package: gsubfn
    #> Loading required package: proto
    #> Loading required package: RSQLite
    df <- structure(list(ID1 = c(1, 2, 3, 4, 5, 6, 7, 8, 9), Value1 = c(2, 
    3, 5, 2, 5, 8, 17, 3, 5), ID2 = c(1, 2, 3, 4, 5, 6, 7, 8, 9), 
        Value2 = c(4, 6, 3, 5, 8, 1, 2, 8, 10)), class = "data.frame", row.names = c(NA, 
    -9L))
    
    # just get min sum
    sqldf('
    select
      min(a.Value1 + b.Value2) as min_sum
    from
      df a
      join df b 
        on a.ID1 + b.ID2 <= 9
    ')
    #>   min_sum
    #> 1       3
     
    # show the rows where min sum occurs
    sqldf('
    select
      a.Value1
      , b.Value2
      , a.ID1
      , b.ID2
    from
      df a
      join df b 
        on a.ID1 + b.ID2 <= 9
    group by
      1 = 1
    having
      a.Value1 + b.Value2 = min(a.Value1 + b.Value2)
    ')
    #>   Value1 Value2 ID1 ID2
    #> 1      2      1   1   6
    

    reprex package (v2.0.1) 于 2021 年 11 月 15 日创建

    【讨论】:

      【解决方案4】:

      另一个班轮,

      filter(transform(df, 'new' = df$Value1 + df$Value2),(df$ID1 + df$ID2 <=9)&(new == min(new)))
      

      【讨论】:

        猜你喜欢
        • 2016-11-28
        • 1970-01-01
        • 2019-11-22
        • 1970-01-01
        • 2015-11-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多