在R中有条件地删除行

6

我有一组数据,其中第一列是一堆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行,并删除其余行。

2个回答

14
为了选择每个“ID”组中具有最小“Number”的行,我们可以使用其中一种聚合函数。 base R选项是aggregate。 使用aggregate,我们可以使用“公式”方法或使用by参数指定分组元素/变量的list来指定分组方式。 使用“公式”方法,我们可以获取每个“ID”的“Number”的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来对'Number'列进行排序,并使用具有by选项的unique选择第一个非重复的'ID'行。(来自@David Arenburgs的评论)

 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”中“Number”最小值所在的行,则可以使用which.min. 使用.I将获取行索引,然后可以用于子集化行。

setDT(df1)[df1[,  .I[which.min(Number)], by = ID]$V1]
或者使用 dplyr,我们使用 slice 来过滤掉每个 'ID' 中具有最小 'Number' 值的行。
df1 %>% 
    group_by(ID) %>%
    slice(which.min(Number))

1
或者 unique(setorder(setDT(df1), Number), by = "ID")。我认为你需要用 which.min 代替 min,因为似乎 OP 始终 想要保留每个 ID 的一行。顺便说一句,很好的 sqldf 解决方案 :) - David Arenburg
@DavidArenburg 謝謝,min只保留單個值,但當有更多列時,which.min將更為通用。 - akrun

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接