根据值减少数据集

时间:2012-12-22 18:11:54

标签: r dataframe

我有一个数据集

dtf<-data.frame(id=c("A","A","A","A","B","B","B","B"), value=c(2,4,6,8,4,6,8,10))

对于每个id,值按升序排序

我想减少dtf,使其仅包含值超过指定限制的每个id的第一行。每id只有一行,应该是value首次超过指定限制的行。

对于此示例,对于5的限制,dtf应减少为:

A 6
B 6

这是一个很好的方法吗?

非常感谢

5 个答案:

答案 0 :(得分:5)

可以使用aggregate

完成
dtf<-data.frame(id=c("A","A","A","A","B","B","B","B"), value=c(2,4,6,8,4,6,8,10))

limit <- 5

aggregate(value ~ id, dtf, function(x) x[x > limit][1])

结果:

  id value
1  A     6
2  B     6

更新:多列的解决方案:

示例数据框dtf2

dtf2 <- data.frame(id=c("A","A","A","A","B","B","B","B"), 
                   value=c(2,4,6,8,4,6,8,10),
                   col3 = letters[1:8],
                   col4 = 1:8)

包含ave的解决方案:

with(dtf2, dtf2[ave(value, id, FUN = function(x) cumsum(x > limit)) == 1, ])

结果:

  id value col3 col4
3  A     6    c    3
6  B     6    f    6

答案 1 :(得分:4)

这是使用data.table的“不错”选项:

library(data.table)
DT <- data.table(dft, key = "id")

DT[value > 5, head(.SD, 1), by = key(DT)]
#    id value
# 1:  A     6
# 2:  B     6

并且,本着共享的精神,使用sqldf的选项可能会很好,这取决于您是否对SQL感觉更舒服。

sqldf("select id, min(value) as value from dtf where value > 5 group by id")
#   id value
# 1  A     6
# 2  B     6

更新:无序源数据,以及具有多列

data.frame

根据您对某些答案的评论,似乎您的“价值”列可能不会像您的示例中那样进行排序,并且您的{{1}中还有其他列}}

以下是这些方案的两种备选方案,一种是data.frame,我发现最容易阅读,最有可能是最快的,另一种是典型的“拆分 - 应用 - 组合”方法,通常需要这样的任务。

首先,一些示例数据:

data.table

其次,dtf2 <- data.frame(id = c("A","A","A","A","B","B","B","B"), value = c(6,4,2,8,4,10,8,6), col3 = letters[1:8], col4 = 1:8) dtf2 # Notice that the value column is not ordered # id value col3 col4 # 1 A 6 a 1 # 2 A 4 b 2 # 3 A 2 c 3 # 4 A 8 d 4 # 5 B 4 e 5 # 6 B 10 f 6 # 7 B 8 g 7 # 8 B 6 h 8 方法:

data.table

其次,基础R的常见“分裂 - 应用 - 组合”方法:

library(data.table)
DT <- data.table(dtf2)
DT # Verify that the data are not ordered
#    id value col3 col4
# 1:  A     6    a    1
# 2:  A     4    b    2
# 3:  A     2    c    3
# 4:  A     8    d    4
# 5:  B     4    e    5
# 6:  B    10    f    6
# 7:  B     8    g    7
# 8:  B     6    h    8
DT[order(value)][value > 5, head(.SD, 1), by = "id"]
#    id value col3 col4
# 1:  A     6    a    1
# 2:  B     6    h    8

答案 2 :(得分:2)

使用aggregate的另一种方法:

> aggregate(value~id, dtf[dtf[,'value'] > 5,], min)
  id value
1  A     6
2  B     6

这取决于要排序的元素,因为它将是min

返回的条目

答案 3 :(得分:2)

也可能是plyrhead的替代方案:

library(plyr)
dtf<-data.frame(id=c("A","A","A","A","B","B","B","B"), value=c(2,4,6,8,4,6,8,10))
limit <- 5
result <- ddply(dtf, "id", function(x) head(x[x$value > limit ,],1) )


    > result
  id value
1  A     6
2  B     6

答案 4 :(得分:1)

这取决于您的data.frame正在排序:

threshold <- 5
foo <- dtf[dtf$value>=threshold,]
foo[c(1,which(diff(as.numeric(as.factor(foo$id)))>0)),]