【问题标题】:subset the data frame based on multiple ranges and save each range as element in the list根据多个范围对数据框进行子集化,并将每个范围保存为列表中的元素
【发布时间】:2020-09-29 18:43:56
【问题描述】:

我想根据属于多个范围的值将数据框制作为列表,以便每个值属于每个范围成为该列表中的一个元素。例如,如果我有 10 个范围和 nrow=n 的数据框,那么我将得到一个包含 10 个数据框的列表。

数据

df<- data.frame(x=seq(33, 37, 0.12), y=seq(31,35, 0.12))
library(data.table)
range<- data.table(start  =c(36.15,36.08,36.02,35.95,35.89,35.82,35.76,35.69),
                   end = c(36.08,36.02,35.95,35.89,35.82,35.76,35.69,35.63))

我试过了

nlist<-list(
     df[which(df$x>36.15),],
     df[which(df$x<=36.15 & df$x>36.08),],
     df[which(df$x<=36.08 & df$x>36.02),],
     df[which(df$x<=36.02 & df$x>35.95),],
     df[which(df$x<=35.95 & df$x>35.89),],
     df[which(df$x<=35.89 & df$x>35.82),],
     df[which(df$x<=35.82 & df$x>35.76),],
     df[which(df$x<=35.76 & df$x>35.69),],
     df[which(df$x<=35.69 & df$x>35.63),],
     df[which(df$x <= 35.63),])

有两个问题。首先,我想循环而不是编写每个范围限制的值。其次,这段代码:

Reduce('+', lapply(nlist, nrow))

产生行的总和 = 35,而我的数据框有 nrow = 34。这个额外的值来自哪里?

【问题讨论】:

    标签: r list range


    【解决方案1】:

    您可以应用范围对象的行

    apply(range, 1, function(z) df[df$x > z[2] & df$x <= z[1],])
    

    【讨论】:

    • 不幸的是,这不包括低于最小值或高于最大值的值的数据帧。
    • 你是对的@AllanCameron,你必须在range 中添加2 行,以Inf/-Inf 开始/结束以捕获它们。
    • 正是丹尼尔。这就是我最后选择cut 的原因,因为它允许你传入一个向量,所以你可以坚持Inf-Inf
    【解决方案2】:

    您可以根据cutting df$x by range$start 获得的级别来split 数据框。你甚至不需要循环:

    nlist <- split(df, cut(df$x, breaks = c(-Inf, range$start, Inf)))
    

    或者,如果您希望它采用相同的格式(倒序的未命名列表,您可以这样做:

    nlist <- setNames(rev(split(df, cut(df$x, breaks=c(-Inf, range$start, Inf)))),NULL)
    

    这也给出了Reduce的正确答案:

    Reduce('+', lapply(nlist, nrow))
    #> [1] 34
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-22
      • 2019-01-30
      • 2013-10-25
      • 1970-01-01
      • 1970-01-01
      • 2015-12-12
      • 1970-01-01
      • 2023-01-28
      相关资源
      最近更新 更多