我有一个包含位置(loc
)的数据框,其中每个位置都有两个区域(type
)和每个区域中的干扰区域(area
)。从我的数据框中,我想保留两个区域都发生干扰的位置。
我以为我可以通过按两个条件设置数据子集来简单地做到这一点,但是使用AND条件(&)
subset(dd, (dd$type == "npr" & dd$area > 0 ) & (dd$type == "buff" & dd$area > 0 ) )
为我提供空输出
[1] loc type area
<0 rows> (or 0-length row.names)
并使用“或”条件(|)
subset(dd, (dd$type == "npr" & dd$area > 0 ) | (dd$type == "buff" & dd$area > 0 ) )
不是我想要的。
loc type area
1 a npr 10
2 a buff 20
4 b buff 10
5 c npr 5
7 d npr 5
8 d buff 5
如何正确区分两种区域类型中干扰区域均大于0的位置?
我的伪数据:
loc<-c("a", "a", "b", "b", "c", "c", "d", "d")
type= rep(c("npr", "buff"), 4)
area = c(10,20,0,10,5,0,5,5)
dd<-data.frame(loc, type, area)
所需的输出:
loc type area
1 a npr 10
2 a buff 20
3 d npr 5
4 d buff 5
答案 0 :(得分:2)
您需要计算一个分组的摘要才能实现。也就是说,你想要
以找出每个loc
在该位置的area
的 all 是否大于0。
对于分组统计信息,我总是发现R有点尴尬,但这是
实现这一目标的一种方法。
首先,使用tapply()
为每个loc
确定是否应该
是否包含:
(include <- tapply(dd$area, dd$loc, function(x) all(x > 0)))
#> a b c d
#> TRUE FALSE FALSE TRUE
然后,我们可以使用loc
值对结果进行索引以获取合适的向量
用以下子集dd
来组成子集:
include[dd$loc]
#> a a b b c c d d
#> TRUE TRUE FALSE FALSE FALSE FALSE TRUE TRUE
dd[include[dd$loc], ]
#> loc type area
#> 1 a npr 10
#> 2 a buff 20
#> 7 d npr 5
#> 8 d buff 5
我们还可以将这些步骤放在subset()
调用中,以避免
创建额外的变量:
subset(dd, tapply(area, loc, function(x) all(x > 0))[loc])
#> loc type area
#> 1 a npr 10
#> 2 a buff 20
#> 7 d npr 5
#> 8 d buff 5
或者,您可以使用dplyr:
library(dplyr)
dd %>%
group_by(loc) %>%
filter(all(area > 0))
#> # A tibble: 4 x 3
#> # Groups: loc [2]
#> loc type area
#> <fct> <fct> <dbl>
#> 1 a npr 10
#> 2 a buff 20
#> 3 d npr 5
#> 4 d buff 5
由reprex package(v0.2.0.9000)创建于2018-07-25。
答案 1 :(得分:2)
我将首先重塑:
loc<-c("a", "a", "b", "b", "c", "c", "d", "d")
type= rep(c("npr", "buff"), 4)
area = c(10,20,0,10,5,0,5,5)
dd<-data.frame(loc, type, area)
library(reshape2)
dd_wide <- dcast(dd, loc ~ type, value.var = "area")
mask <- subset(dd_wide, buff > 0 & npr > 0)[["loc"]]
subset(dd, loc %in% mask)
# one line:
subset(dd, loc %in% subset(dcast(dd, loc ~ type, value.var = "area"), buff > 0 & npr > 0)[["loc"]])