仅保留与数据框中的 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
一个base
R解:
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, ]
我有以下数据(这是一个模拟版本)并且我正在使用 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
一个base
R解:
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, ]