我正在尝试删除具有抵消值的行。
library(dplyr)
a <- c(1, 1, 1, 1, 2, 2, 2, 2,2,2)
b <- c("a", "b", "b", "b", "c", "c","c", "d", "d", "d")
d <- c(10, 10, -10, 10, 20, -20, 20, 30, -30, 30)
o <- c("A", "B", "C", "D", "E", "F", "G", "H", "I", "J")
df <- tibble(ID = a, SEQ = b, VALUE = d, OTHER = o)
生成此有序表,按ID和SEQ。
分组> df
# A tibble: 10 x 4
ID SEQ VALUE OTHER
<dbl> <chr> <dbl> <chr>
1 1 a 10 A
2 1 b 10 B
3 1 b -10 C
4 1 b 10 D
5 2 c 20 E
6 2 c -20 F
7 2 c 20 G
8 2 d 30 H
9 2 d -30 I
10 2 d 30 J
我想删除行对(2,3),(5,6),(8,9),因为VALUE否定匹配前一行中的VALUE。
我希望结果表是
> df2
# A tibble: 4 x 4
ID SEQ VALUE OTHER
<dbl> <chr> <dbl> <chr>
1 1 a 10 A
2 1 b 10 D
3 2 c 20 G
4 2 d 30 J
我知道我无法使用group_by %>% summarize
,因为我需要保留在OTHER中的值。我查看了dplyr::lag()
功能,但我不知道这有什么用。我相信我可以使用某种类型的for each
循环遍历表,并生成可用于删除行的逻辑向量,但我希望有更优雅的解决方案。
答案 0 :(得分:1)
怎么样:
vec <- cbind(
c(head(df$VALUE,-1) + df$VALUE[-1], 9999) ,
df$VALUE + c(9999, head(df$VALUE,-1))
)
vec <- apply(vec,1,prod)
vec <- vec!=0
df[vec,]
# A tibble: 4 x 4
ID SEQ VALUE OTHER
<dbl> <chr> <dbl> <chr>
1 1 a 10 A
2 1 b 50 D
3 2 c 60 G
4 2 d 70 J
我们的想法是取你的VALUE
字段并用它的略微子集版本减去它。当结果为0时,比删除该行。
答案 1 :(得分:1)
这是dplyr
的另一个解决方案。不确定您在评论中提到的边缘情况,但可以随意使用我的解决方案进行测试:
library(dplyr)
df %>%
group_by(ID, SEQ) %>%
mutate(diff = VALUE + lag(VALUE),
diff2 = VALUE + lead(VALUE)) %>%
mutate_at(vars(diff:diff2), funs(coalesce(., 1))) %>%
filter((diff != 0 & diff2 != 0)) %>%
select(-diff, -diff2)
<强>结果:强>
# A tibble: 4 x 4
# Groups: ID, SEQ [4]
ID SEQ VALUE OTHER
<dbl> <chr> <dbl> <chr>
1 1 a 10 A
2 1 b 50 D
3 2 c 60 G
4 2 d 70 J
注意:强>
此解决方案首先创建两个diff
列,一个添加lag
,另一个添加lead
VALUE
到每个VALUE
。只有偏移列在diff
或diff2
中都会为零,因此我会过滤掉这些行,从而产生所需的输出。