有条件地删除R中的行
Posted
技术标签:
【中文标题】有条件地删除R中的行【英文标题】:Deleting rows in R conditionally 【发布时间】:2015-08-31 07:55:06 【问题描述】:我有一个数据,其中第一列是一堆 ID 号(有些重复),第二列只是一堆数字。我需要一种方法,根据第二列中的最小数字将每个 ID 号仅保留一次。
Row# ID Number
1 10 180
2 12 167
3 12 182
4 12 135
5 15 152
6 15 133
例如:我只想在此处保留第 1、4 和 6 行并删除其余的
【问题讨论】:
【参考方案1】:要为每个“ID”组选择具有最小“编号”的行,我们可以使用按组聚合功能之一。 base R
选项是 aggregate
。使用aggregate
,我们可以使用“公式”方法或使用by
参数指定分组元素/变量的list
。使用formula
方法,我们得到每个“ID”的“数字”min
值。
aggregate(Number~ID, df1, FUN=min)
或者我们可以使用更快的选项data.table
。在这里,我们将 'data.frame' 转换为 'data.table' (setDT(df1)
),按 'ID' 分组,我们得到“Number”的min
值。
library(data.table)
setDT(df1)[, list(Number=min(Number)), by = ID]
或者这也可以使用setorder
到order
'Number' 列并使用unique
和by
选项来选择第一个非重复的'ID' 行。 (来自@David Arenburgs 的 cmets)
unique(setorder(setDT(df1), Number), by = "ID")
或者使用dplyr
,我们按“ID”分组并获得带有summarise
的子集行。
library(dplyr)
df1 %>%
group_by(ID) %>%
summarise(Number= min(Number))
或者我们可以使用sqldf
语法来获取数据子集。
library(sqldf)
sqldf('select ID,
min(Number) as Number
from df1
group by ID')
更新
如果有多个列,并且您想根据每个“ID”的“数字”最小值获取行,则可以使用which.min
。使用.I
将获得行索引,并可用于对行进行子集化。
setDT(df1)[df1[, .I[which.min(Number)], by = ID]$V1]
或者使用dplyr
,我们使用slice
过滤出每个“ID”的min
值为“Number”的行
df1 %>%
group_by(ID) %>%
slice(which.min(Number))
【讨论】:
或unique(setorder(setDT(df1), Number), by = "ID")
。我还认为您需要which.min
而不是min
,因为似乎OP 总是希望每个ID
保留一行。顺便说一句,很好的sqldf
解决方案:)
@DavidArenburg 谢谢,min
只保留单个值,但当有更多列时,which.min
会更通用。【参考方案2】:
或者
do.call(rbind,
lapply(split(df1, df1$ID), function(x) subset(x, Number == min(Number))))
#ID Number
#10 10 180
#12 12 135
#15 15 133
【讨论】:
以上是关于有条件地删除R中的行的主要内容,如果未能解决你的问题,请参考以下文章