仅当行与上方和下方的行相同时,如何删除行?

时间:2019-09-16 01:59:33

标签: r

我有一个很大的数据框,其中除包含标识符的前四行外,每一行都是不同的字母系列。

我试图在大型数据帧(〜30,000行,〜200列)中仅使同一行(从第5列开始)的第一次出现和最后一次出现彼此相邻。 换句话说,如何删除除了第一和最后相同的连续行以外的所有行?

我环顾四周,但是我能找到的唯一代码仅保留每个副本的一个副本。

举一个我想做的简单例子。

Data <- data.frame(Met = c("qwr", "asd", "zxc", "ert", "dfg", "cvb", 
                           "tyu", "fgh", "vbn", "uio", "jkl", "bnm"),
                   A = c(1, 2, 2, 2, 3, 3, 3, 4, 4, 2, 2, 2),
                   B = c(1, 2, 2, 2, 3, 3, 3, 4, 4, 2, 2, 2),
                   C = c(1, 2, 2, 2, 3, 3, 3, 4, 4, 2, 2, 2),
                   D = c(1, 2, 2, 2, 3, 3, 3, 4, 4, 2, 2, 2)
    )

Data

   Met A B C D
1  qwr 1 1 1 1
2  asd 2 2 2 2
3  zxc 2 2 2 2
4  ert 2 2 2 2
5  dfg 3 3 3 3
6  cvb 3 3 3 3
7  tyu 3 3 3 3
8  fgh 4 4 4 4
9  vbn 4 4 4 4
10 uio 2 2 2 2
11 jkl 2 2 2 2
12 bnm 2 2 2 2

将成为:

End

  Met A B C D
1 qwr 1 1 1 1
2 asd 2 2 2 2
3 ert 2 2 2 2
4 dfg 3 3 3 3
5 tyu 3 3 3 3
6 fgh 4 4 4 4
7 vbn 4 4 4 4
8 uio 2 2 2 2
9 bnm 2 2 2 2

我一直在以不同的方式来解决这个问题,但是我感觉好像没有什么地方接近。我最喜欢R,但是愿意尝试其他语言。

3 个答案:

答案 0 :(得分:2)

我猜您正在尝试删除连续出现的4列。我们可以使用unite组合4列,并使用data.table::rleid来获得连续出现的ID,并在每个组中仅选择第一行和最后一行。

library(dplyr)
Data %>%
   tidyr::unite(temp, names(Data)[-1], remove = FALSE) %>%
   group_by(group = data.table::rleid(temp)) %>%
   slice(if(n() > 1) c(1L,n()) else 1L) %>%
   ungroup() %>%
   select(-temp, -group)

#   Met     A     B     C     D
#  <fct> <dbl> <dbl> <dbl> <dbl>
#1 qwr       1     1     1     1
#2 asd       2     2     2     2
#3 ert       2     2     2     2
#4 dfg       3     3     3     3
#5 tyu       3     3     3     3
#6 fgh       4     4     4     4
#7 vbn       4     4     4     4
#8 uio       2     2     2     2
#9 bnm       2     2     2     2

或者@thelatemail建议的一种更简单的方法是将rleidvduplicated一起使用

inds <- data.table::rleidv(Data[-1])
Data[!duplicated(inds) | !duplicated(inds, fromLast = TRUE), ]

答案 1 :(得分:1)

一种解决方法是添加行号和dplyr的group_by,然后选择该组中的最小和最大行号。

不清楚是要对头四列还是除头四列以外的所有内容进行分组,但是无论哪种情况,都可以轻松修改此代码(只需更改以first_included:last_included形式提供的列的范围)。无论哪种情况,请确保排除行号列。

library(dplyr)
library(magrittr)
Data %>% 
   mutate(row.id = row_number()) %>% 
   group_by_at(vars(fifth.col:last.col)) %>% 
   filter(row.id == max(row.id) || row.id == min(row.id)) %>% 
   ungroup %>% 
   select(-row.id)

答案 2 :(得分:0)

inds = ave(1:NROW(Data),
           with(rle(Reduce(paste, Data[-1])), rep(seq_along(values), lengths)),
           FUN = function(x){
               id = seq_along(x)
               id %in% range(id)
           }) == 1
Data[inds,]
#   Met A B C D
#1  qwr 1 1 1 1
#2  asd 2 2 2 2
#4  ert 2 2 2 2
#5  dfg 3 3 3 3
#7  tyu 3 3 3 3
#8  fgh 4 4 4 4
#9  vbn 4 4 4 4
#10 uio 2 2 2 2
#12 bnm 2 2 2 2