【问题标题】:Using Ifelse in a dataframe在数据框中使用 Ifelse
【发布时间】:2016-05-18 20:22:43
【问题描述】:

我使用的数据框是

> df <- data.frame(Name=c("Joy","Jane","Jack","Jad"),M1=c(10,40,55,90))
> df
  Name M1
1  Joy 10
2 Jane 40
3 Jack 55
4  Jad 90

> df$Final <- ifelse(df$M1<=50,60,max(75,df$M1))
> df
  Name M1 Final
1  Joy 10    60
2 Jane 40    60
3 Jack 55    90
4  Jad 90    90

如果 M1 值小于或等于 50,那么我需要 60 作为我的最终值,而如果 M1 值大于 50,那么我需要最大值 m(75,M1)。在 Jack 的情况下,M1 是 55,所以我应该得到 max(75,55),即 75。我认为它给了我整个 M1 列的最大值。如何避免这种情况?

期望的输出

  Name M1 Final
1  Joy 10    60
2 Jane 40    60
3 Jack 55    75
4  Jad 90    90

【问题讨论】:

  • pmax(df$M1, c(60, 75)[1 + (df$M1 > 50)])
  • 就像 Imo 所说,只需将 max 更改为 pmax 就可以了

标签: r if-statement dataframe


【解决方案1】:

您也可以使用pmax 代替max

ifelse(df$M1 <= 50, 60, pmax(75, df$M1))

从帮助文件中,pmax 获取

一个或多个向量(或矩阵)作为参数并返回一个向量,给出向量的“平行”最大值......。结果的第一个元素是所有参数的第一个元素中的最大值……,结果的第二个元素是所有参数的第二个元素中的最大值……等等。

因此,ifelse 的第三个参数“else”值是成对最大值 75(根据需要循环多次)和 df$M1 的值。

【讨论】:

  • 不错的一个。在没有ifelse()replace(pmax(75, df$M1), df$M1 &lt;= 50, 60) 的情况下完成,但不确定是否有任何效率优势。
  • 感谢您的提示。我今天刚遇到replace 函数。我将它列在我的“进一步研究”功能列表中,该功能还在继续增长。
  • @Richard 我认为一种有效的方法可能涉及 findInterval (以避免测试两个不等式):s = split(seq_along(m), findInterval(m, c(50, 75)))[1:2]; m[unlist(s)] = rep(c(60,75), lengths(s))
【解决方案2】:

怎么样:

ifelse(df$M1<=50,60,ifelse(df$M1>75,df$M1,75))

【讨论】:

    【解决方案3】:

    你实际上是在描述一个规则,比如......

    • 最多 50 个,替换为 60 个
    • 最多 75,替换为 75
    • 最多 x,替换为 y
    • ...

    如果我们将规则放入 data.frame 中,它会更加明确,并且可能允许更有效地推导结果(而不是计算许多不等式)。这里有两种方法:

    findInterval

    m = data.frame(up_to = c(50, 75), replace_with = c(60, 75))
    
    df$Final = df$M1
    r = m$replace_with[ findInterval(df$M1, m$up_to) + 1L ]
    df$Final = replace(df$M1, !is.na(r), na.omit(r))
    

    data.table滚动连接

    library(data.table)    
    setDT(df)
    
    m = data.table(up_to = c(50, 75), replace_with = c(60, 75))
    
    df[, Final := M1]
    r = m[df, on=c(up_to = "M1"), roll=-Inf][!is.na(replace_with), Final := replace_with]$Final
    df[, Final := r]
    

    【讨论】:

    • 会不会比c(rep(60, 50),rep(75, 25), 76:max(df$M1))[df$M1]效率更高?
    • @HubertL 是的,我喜欢这个主意;如果 M1 是一个小范围的整数向量,它应该工作得很好。不过,一般规则的扩展(存储在类似m 的结构中)并不明显。例如,有一些极端情况,比如max(df$M1) 恰好小于 75;我们也应该能够利用min(df$M1),我猜(虽然我不确定如何编码)。如果您能弄清楚,您可以将其添加到您的答案中或单独发布一个。
    【解决方案4】:

    如果d$M1 仅包含正数且非空integers,则使用查找可能更有效:

    lookup <-  c(rep(60, 50),rep(75, 25), 76:max(df$M1,76))
    lookup[df$M1]
    

    如果它还包含负数或空integers:

    lookup <-  c(rep(60, 50-min(df$M1)+1),rep(75, 25), 76:max(df$M1,76))
    lookup[df$M1-min(df$M1)+1]
    

    【讨论】:

      【解决方案5】:

      您可以使用dplyrrowwise

      library(dplyr)
      
      df %>%
        rowwise() %>%
        mutate(Final = ifelse(M1<=50,60,max(75,M1)))
      

      【讨论】:

        猜你喜欢
        • 2022-12-07
        • 1970-01-01
        • 2018-06-29
        • 2017-12-23
        • 1970-01-01
        • 1970-01-01
        • 2021-12-06
        • 1970-01-01
        • 2020-12-30
        相关资源
        最近更新 更多