【问题标题】:cutting interval based on limits in a list根据列表中的限制切割间隔
【发布时间】:2018-12-24 14:16:30
【问题描述】:

我有以下包含 4 个数字列的数据框:

df <- structure(list(a = c(0.494129340746821, 1.0182303327812, 0.412227511922328, 
0.204436644926016, 0.707038309818134, -0.0547300783473556, 1.02124944293185, 
0.381284586356091, 0.375197843213519, -1.18172401075089), b = 
c(-1.34374367808722, 
-0.724644569211516, -0.618107980582741, -1.79274868750102, 
-3.03559838445132, 
-0.205726144151615, -0.441511286334811, 0.126660637747845, 
0.353737902975931, 
-0.26601393471207), c = c(1.36922677098999, -1.81698348029464, 
-0.846111260721092, 0.121256015837603, -1.16499681749603, 1.14145675696301, 
-0.782988942359773, 3.25142254765012, -0.132099541183856, -0.242831877642412
), d = c(-0.30002630673509, -0.507496812070994, -2.59870853299723, 
-1.30109828239028, 1.05029458887117, -0.606381379180569, -0.928822706709913, 
-0.68324741261771, -1.17980245487707, 2.20174180936794)), row.names = c(NA, 
-10L), class = c("tbl_df", "tbl", "data.frame"))

我想创建两个新的因子列,其中我根据列表L 中给出的值对第 2 列和第 3 列进行分组:

ColsToChoose = c(2,3)
L = list()
L[[1]] = c(-0.3, 0.7)
L[[2]] = c(-1, 0.5, 1)

df %>% mutate_at(ColsToChoose, funs(intervals = cut(., c(-Inf, L[[.]], Inf))))

也就是说,我希望得到两个新列,第一个称为 intervals_b 表示列 b(第 2 列)的值是否介于 -Inf 和 -0.3、-0.3 和 0.7 或 0.7 之间Inf,对于列 c,类似:-Inf 到 -1,-1 到 0.5,0.5 到 1 和 1 到 Inf

我收到一个错误:

mutate_impl(.data, dots) 中的错误: 评估错误:递归索引在级别 2 失败

我想在一般情况下这样做,这就是我使用隐式名称的原因。

有什么想法吗?

【问题讨论】:

    标签: r list dplyr


    【解决方案1】:

    您可以并行执行此基本 R mapply 传递 ColsToChoosedfL 以获得范围。

    df[paste0("interval", names(df)[ColsToChoose])] <- 
                   mapply(function(x, y) cut(x, c(-Inf, y, Inf)), df[ColsToChoose], L)
    
    df
    
    #        a      b      c      d   intervalb   intervalc
    #     <dbl>  <dbl>  <dbl>  <dbl>   <chr>       <chr>    
    # 1  0.494  -1.34   1.37  -0.300 (-Inf,-0.3] (1, Inf] 
    # 2  1.02   -0.725 -1.82  -0.507 (-Inf,-0.3] (-Inf,-1]
    # 3  0.412  -0.618 -0.846 -2.60  (-Inf,-0.3] (-1,0.5] 
    # 4  0.204  -1.79   0.121 -1.30  (-Inf,-0.3] (-1,0.5] 
    # 5  0.707  -3.04  -1.16   1.05  (-Inf,-0.3] (-Inf,-1]
    # 6 -0.0547 -0.206  1.14  -0.606 (-0.3,0.7]  (1, Inf] 
    # 7  1.02   -0.442 -0.783 -0.929 (-Inf,-0.3] (-1,0.5] 
    # 8  0.381   0.127  3.25  -0.683 (-0.3,0.7]  (1, Inf] 
    # 9  0.375   0.354 -0.132 -1.18  (-0.3,0.7]  (-1,0.5] 
    #10 -1.18   -0.266 -0.243  2.20  (-0.3,0.7]  (-1,0.5] 
    

    使用相同方法的tidyverse 方法

    library(tidyverse)
    
    bind_cols(df, 
        map2(df[ColsToChoose], L, ~ cut(.x, c(-Inf, .y, Inf))) %>%
        data.frame() %>%
        rename_all(paste0, "_interval"))
    

    这给出了与上面相同的输出。

    【讨论】:

    • 很好的解决方案。但是有没有办法用dplyr 做到这一点?只是出于好奇
    • 是的,您可以使用purrr::map2map2(df[ColsToChoose], L, function(x, y) cut(x, c(-Inf, y, Inf))) 来做到这一点
    猜你喜欢
    • 2011-08-10
    • 1970-01-01
    • 1970-01-01
    • 2021-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多