仅保留与数据框中的 ID 对应的两行

Keep only two rows corresponding to an ID in a data frame

我有以下数据(这是一个模拟版本)并且我正在使用 R。

ID m
1  m1
1  m2
1  m3
2  m1
2  m2
3  m1
3  m2
3  m3
3  m4
4  m1

每个 ID 都有一个 m1 行,其余的 m 在 ID 中的长度可变。我想保留每个 ID 对应的 m1 值和最后一个值。理想的输出应该是这样的:

ID m
1  m1
1  m3
2  m1
2  m2
3  m1
3  m4
4  m1

非常感谢您。

一个选项是使用 data.table

将 'data.frame' 转换为 'data.table' (setDT(df1))。按 'ID' 列分组,并根据逻辑条件对数据集进行子集化。如果行数为 1 (if(.N==1)),我们取 'm' 的值即。每组的唯一值或 else,我们将每个值 'm1' (m[m=='m1']) 与最后一个值 'm' (m[.N]) 连接起来每组

library(data.table)
setDT(df1)[, list(m=if(.N==1) m else c(m[m=='m1'], m[.N])), by = ID]
#   ID  m
#1:  1 m1
#2:  1 m3
#3:  2 m1
#4:  2 m2
#5:  3 m1
#6:  3 m4
#7:  4 m1

dplyr相同的结果:

df %>% 
   group_by(ID) %>%
   filter(row_number()==n()|m=='m1')


Source: local data frame [7 x 2]
Groups: ID

  ID  m
1  1 m1
2  1 m3
3  2 m1
4  2 m2
5  3 m1
6  3 m4
7  4 m1

一个baseR解:

df[ave(logical(nrow(df)),df$ID,FUN=function(x) seq_along(x) %in% c(1,length(x))),]
#   ID  m
#1   1 m1
#3   1 m3
#4   2 m1
#5   2 m2
#6   3 m1
#9   3 m4
#10  4 m1

另一种 base R 方法是使用拆分、应用、组合样式过滤器:

`rownames<-`(do.call(rbind, lapply(split(df,df$ID), function(x) {
  x[x$m=="m1"|seq(nrow(x))==nrow(x),]})),NULL)
#   ID  m
# 1  1 m1
# 2  1 m3
# 3  2 m1
# 4  2 m2
# 5  3 m1
# 6  3 m4
# 7  4 m1

函数的核心是x[x$m=="m1"|seq(nrow(x))==nrow(x),]。每个组由等于 "m1" 或最后一行的列 "m" 值子集。根据需要,所有中间行都将被排除在外。 split(df,df$ID) 按 ID 分割数据框。 do.call(rbind.. 将所有内容重新组合到一个数据框中。 'rownames<-'...,NULL) 使行号统一。

一堆 base R one 衬垫:

x[c(diff(x$ID),1) == 1 | c(1,diff(x$ID)) == 1, ]
x[(c(diff(x$ID),1) + c(1,diff(x$ID))) == 1, ]
x[x$m == 'm1' | c((x$m == 'm1')[-1],TRUE), ]
x[pmax(x$m == 'm1',c((x$m == 'm1')[-1],1)) == 1, ]