使用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