【问题标题】:apply subset function to columns using other dataset with min/max values使用具有最小值/最大值的其他数据集将子集函数应用于列
【发布时间】:2023-12-16 11:04:01
【问题描述】:

我正在尝试将子集函数应用于具有来自另一个数据集的最小值和最大值的每一列。

最小可重现示例:

df <- mtcars

两列的最小/最大限制:

dfLimits <- data.frame(Names = c("hp","wt"), Min = c(160,1.6), 
                       Max = c(220,NA),stringsAsFactors = F)`

Names   Min  Max
 hp     160   220
 wt     1.6   NA

尝试使用apply 函数实现以下函数的结果,因为在我的情况下,我有很多列需​​要在两个数据集之间进行匹配并设置限制。

df %>%  subset(hp < 220 & hp > 160 & wt > 1.6)`

【问题讨论】:

    标签: r subset apply tidyr


    【解决方案1】:

    也许不是最好的解决方案,但我们可以动态创建表达式并使用eval(parse()) 进行评估。我们将NA 的值分别替换为Inf/-Inf 中的Max/Min

    dfLimits$Max[is.na(dfLimits$Max)] <- Inf
    dfLimits$Min[is.na(dfLimits$Min)] <- -Inf
    
    
    subset(df, eval(parse(text = paste(dfLimits$Names, ">", dfLimits$Min, "&",
                          dfLimits$Names, "<", dfLimits$Max, collapse = " & "))))
    
    
    #                    mpg cyl  disp  hp drat    wt  qsec vs am gear carb
    #Hornet Sportabout   18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
    #Merc 450SE          16.4   8 275.8 180 3.07 4.070 17.40  0  0    3    3
    #Merc 450SL          17.3   8 275.8 180 3.07 3.730 17.60  0  0    3    3
    #Merc 450SLC         15.2   8 275.8 180 3.07 3.780 18.00  0  0    3    3
    #Cadillac Fleetwood  10.4   8 472.0 205 2.93 5.250 17.98  0  0    3    4
    #Lincoln Continental 10.4   8 460.0 215 3.00 5.424 17.82  0  0    3    4
    #Pontiac Firebird    19.2   8 400.0 175 3.08 3.845 17.05  0  0    3    2
    #Ferrari Dino        19.7   6 145.0 175 3.62 2.770 15.50  0  1    5    6
    

    paste 的输出是:

    paste(dfLimits$Names, ">", dfLimits$Min, "&", 
          dfLimits$Names, "<", dfLimits$Max, collapse = " & ")
    
    #[1] "hp > 160 & hp < 220 & wt > 1.6 & wt < Inf"
    

    如果对dplyr 解决方案感兴趣,我们可以在filterparse_expr 中使用相同的paste 表达式。

    library(dplyr)
    library(rlang)
    
    df %>%
      filter(eval(parse_expr(paste(dfLimits$Names, ">", dfLimits$Min, "&",
                  dfLimits$Names, "<", dfLimits$Max, collapse = " & "))))
    

    【讨论】:

    • 谢谢,非常好的方法。就我而言,列名以 1_wt2_hp 之类的数字开头,因此无法解析,您知道解决方法吗?
    • 我不完全确定您的数据的结构,但您可以尝试使用pivot_longer 获取长格式数据,在_ 上使用separate,以便1 和@ 987654341@分到不同的列然后用上面的方法。
    最近更新 更多