【问题标题】:Split data.frame based on condition根据条件拆分 data.frame
【发布时间】:2016-05-20 01:04:32
【问题描述】:

假设我有以下 data.frame,其中 pos 是位置坐标。我已经包含了一个变量 thresh,其中 val 大于给定的阈值 t。

set.seed(123)
n <- 20
t <- 0
DF <- data.frame(pos = seq(from = 0, by = 0.3, length.out = n),
                 val = sample(-2:5, size = n, replace = TRUE))
DF$thresh <- DF$val > t
DF

##    pos val thresh
## 1  0.0   0  FALSE
## 2  0.3   4   TRUE
## 3  0.6   1   TRUE
## 4  0.9   5   TRUE
## 5  1.2   5   TRUE
## 6  1.5  -2  FALSE
## 7  1.8   2   TRUE
## 8  2.1   5   TRUE
## 9  2.4   2   TRUE
## 10 2.7   1   TRUE
## 11 3.0   5   TRUE
## 12 3.3   1   TRUE
## 13 3.6   3   TRUE
## 14 3.9   2   TRUE
## 15 4.2  -2  FALSE
## 16 4.5   5   TRUE
## 17 4.8  -1  FALSE
## 18 5.1  -2  FALSE
## 19 5.4   0  FALSE
## 20 5.7   5   TRUE

如何获得 val 为正的区域坐标,即在上面的示例中:

0.3 - 1.2,
1.8 - 3.9,
4.5 - 4.5,
5.7 - 5.7

我曾想过通过 thresh 拆分 data.frame,然后从每个 data.frame 列表元素的第一行和最后一行访问 pos,但这只会将所有 TRUE 和 FALSE 子集组合在一起。有没有办法根据 TRUE 值将 thresh 变量转换为字符,并丢弃 FALSE 值?

split(DF, DF$thresh) # not what I want


## $`FALSE`
##    pos val thresh
## 1  0.0   0  FALSE
## 6  1.5  -2  FALSE
## 15 4.2  -2  FALSE
## 17 4.8  -1  FALSE
## 18 5.1  -2  FALSE
## 19 5.4   0  FALSE
## 
## $`TRUE`
##    pos val thresh
## 2  0.3   4   TRUE
## 3  0.6   1   TRUE
## 4  0.9   5   TRUE
## 5  1.2   5   TRUE
## 7  1.8   2   TRUE
## 8  2.1   5   TRUE
## 9  2.4   2   TRUE
## 10 2.7   1   TRUE
## 11 3.0   5   TRUE
## 12 3.3   1   TRUE
## 13 3.6   3   TRUE
## 14 3.9   2   TRUE
## 16 4.5   5   TRUE
## 20 5.7   5   TRUE

我尝试过的另一件笨重的事情是cumsum,但它再次包含错误行:

split(DF, cumsum(DF$thresh == 0)) # not what I want but close to it...


## $`1`
##   pos val thresh
## 1 0.0   0  FALSE
## 2 0.3   4   TRUE
## 3 0.6   1   TRUE
## 4 0.9   5   TRUE
## 5 1.2   5   TRUE
## 
## $`2`
##    pos val thresh
## 6  1.5  -2  FALSE
## 7  1.8   2   TRUE
## 8  2.1   5   TRUE
## 9  2.4   2   TRUE
## 10 2.7   1   TRUE
## 11 3.0   5   TRUE
## 12 3.3   1   TRUE
## 13 3.6   3   TRUE
## 14 3.9   2   TRUE
## 
## $`3`
##    pos val thresh
## 15 4.2  -2  FALSE
## 16 4.5   5   TRUE
## 
## $`4`
##    pos val thresh
## 17 4.8  -1  FALSE
## 
## $`5`
##    pos val thresh
## 18 5.1  -2  FALSE
## 
## $`6`
##    pos val thresh
## 19 5.4   0  FALSE
## 20 5.7   5   TRUE

【问题讨论】:

  • 没有看到 split 命令有任何问题。无论如何,不​​要拆分,为什么不直接使用DF[DF$thresh==T, ]
  • @AdamQuek 因为这会将所有 TRUE 行组合在一起,但我想访问确切的“区域”。走你的路会给我0.3 - 5.7的限制......

标签: r


【解决方案1】:

这是data.table 的一个选项。我们使用rleid 创建一个分组变量,根据'thresh' 和split 对'pos' 进行子集化。

DT <- setDT(DF)[,pos[thresh] ,.(gr=rleid(thresh))]
split(DT$V1, DT$gr)
#$`2`
#[1] 0.3 0.6 0.9 1.2

#$`4`
#[1] 1.8 2.1 2.4 2.7 3.0 3.3 3.6 3.9

#$`6`
#[1] 4.5

#$`8`
#[1] 5.7

或者我们可以使用base R 中的rle 创建分组变量,然后在此基础上使用split

gr <- inverse.rle(within.list(rle(DF$thresh), values <- seq_along(values)))
with(DF, split(pos[thresh], gr[thresh]))

或者正如@thelatemail 提到的,cumsum 也可以用于在使用 'thresh' 进行子集化后进行分组。

 with(DF, split(pos[thresh],cumsum(!thresh)[thresh]))

【讨论】:

  • 替代 - split(DF$pos[DF$thresh],cumsum(!DF$thresh)[DF$thresh])
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-17
  • 2010-10-31
  • 1970-01-01
  • 2018-03-03
  • 1970-01-01
  • 2020-03-20
  • 1970-01-01
相关资源
最近更新 更多