使用dplyr按组获取序列中的第一行和最后一行
我试图使用使用dplyr按组获取序列中的第一行和最后一行,r,dplyr,R,Dplyr,我试图使用dplyr按组获取重复值的第一行和最后一行。我这样做是为了提高效率,尤其是为了使绘图速度更快 这不是重复的,因为我没有要求严格的第一行和最后一行;我要求按级别分组的第一行和最后一行(在我的案例中为1和0),可能出现在多个块中 这里有一个例子。假设我要删除C列中所有冗余的1和0,同时保持A和B的完整性 df = data.frame( A = rep(c("a", "b"), each = 10), B = rep(c(1:10), 2), C = c(1,0,0
dplyr
按组获取重复值的第一行和最后一行。我这样做是为了提高效率,尤其是为了使绘图速度更快
这不是重复的,因为我没有要求严格的第一行和最后一行;我要求按级别分组的第一行和最后一行(在我的案例中为1和0),可能出现在多个块中
这里有一个例子。假设我要删除C列中所有冗余的1和0,同时保持A和B的完整性
df = data.frame(
A = rep(c("a", "b"), each = 10),
B = rep(c(1:10), 2),
C = c(1,0,0,0,0,0,1,1,1,1,0,0,0,1,0,0,0,0,0,1))
A B C
a 1 1
a 2 0
a 3 0
a 4 0
a 5 0
a 6 0
a 7 1
a 8 1
a 9 1
a 10 1
b 1 0
b 2 0
b 3 0
b 4 1
b 5 0
b 6 0
b 7 0
b 8 0
b 9 0
b 10 1
最终结果应如下所示:
A B C
a 1 1
a 2 0
a 6 0
a 7 1
a 10 1
b 1 0
b 3 0
b 4 1
b 5 0
b 9 0
b 10 1
使用
unique
将不会删除任何内容,或者只使用1或0中的一个,而不会保留我试图实现的开始和结束质量。有没有一种不使用循环的方法可以做到这一点,也许可以使用dplyr
或forcats
?我认为slice
应该可以让你接近:
df %>%
group_by(A,C) %>%
slice(c(1, n()))
给予
给予
一个解决方案:
C_filter <- function(x) {
!sapply(1:length(x), function(i) {
identical(x[i], x[i-1])
}) | !sapply(1:length(x), function(i) {
identical(x[i], x[i+1])
})
}
df %>% group_by(A) %>% filter(C_filter(C))
A B C
1 a 1 1
2 a 2 0
3 a 6 0
4 a 7 1
5 a 10 1
6 b 1 0
7 b 3 0
8 b 4 1
9 b 5 0
10 b 9 0
11 b 10 1
C_filter%group_by(A)%%>%filter(C))
A、B、C
一一一一
2 a 2 0
3 a 6 0
4 a 7 1
5 a 10 1
6b10
7B30
8 b 4 1
9 b 5 0
10 b 9 0
11 b 10 1
很有趣,这比我一直在做的要好。还是少了几行。。。比如a-7,b-3和b-5。你知道为什么吗?我不知道为什么这个问题/答案吸引了如此多的反对票。对有用的贡献投了赞成票。我注意到你没有按(A)分组;你的问题只说明了C
列控制了这些组——我添加了一种方法,还可以检查A
是否发生了变化(在本例中给出了相同的输出),非常感谢。我试图提供一个说明性的例子,但很难做出一个对未来用户同样适用的最小/可复制的例子。我不确定为什么这个问题/答案会吸引如此多的反对票。投票赞成有用的贡献。@zx8754我编辑了我的问题,以详细说明我所问的问题与您链接的问题之间的差异。例如,他们得到了不同的结果,这些结果对纵向队列数据具有有用的影响。在R库中,笨拙的df[unique(unlist(unlist)(tapply(seq_-along(df$C))、list(df$A、cumsum(C(1,abs)(diff(df$Cщщщ))、FUN=函数(i)C(head(i,i,1)、tail(i,1щщщщщ)))),]))对示例有效。
df %>%
mutate(groupChanged = (C != lag(C, default = C[1]))
, toCutBy = cumsum(groupChanged)
) %>%
group_by(toCutBy) %>%
slice(c(1, ifelse(n() == 1, NA, n())))
A B C groupChanged toCutBy
<chr> <int> <dbl> <lgl> <int>
1 a 1 1 FALSE 0
2 a 2 0 TRUE 1
3 a 6 0 FALSE 1
4 a 7 1 TRUE 2
5 a 10 1 FALSE 2
6 b 1 0 TRUE 3
7 b 3 0 FALSE 3
8 b 4 1 TRUE 4
9 b 5 0 TRUE 5
10 b 9 0 FALSE 5
11 b 10 1 TRUE 6
df %>%
mutate(groupChanged = (C != lag(C, default = C[1]) |
A != lag(A, default = A[1]))
, toCutBy = cumsum(groupChanged)
) %>%
group_by(toCutBy) %>%
slice(c(1, ifelse(n() == 1, NA, n())))
C_filter <- function(x) {
!sapply(1:length(x), function(i) {
identical(x[i], x[i-1])
}) | !sapply(1:length(x), function(i) {
identical(x[i], x[i+1])
})
}
df %>% group_by(A) %>% filter(C_filter(C))
A B C
1 a 1 1
2 a 2 0
3 a 6 0
4 a 7 1
5 a 10 1
6 b 1 0
7 b 3 0
8 b 4 1
9 b 5 0
10 b 9 0
11 b 10 1