比较每组中的第一次和最后一次观察

时间:2014-08-07 19:15:28

标签: r

我有这样的数据集:

df <- data.frame(group = c(rep(1,3),rep(2,2), rep(3,3),rep(4,3),rep(5, 2)), score = c(30, 10, 22, 44, 50, 5, 20, 1,35, 2, 60, 14,5))

   group score
1      1    30
2      1    10
3      1    22
4      2    44
5      2    50
6      3     5
7      3    20
8      3     1
9      4    35
10     4     2
11     4    60
12     5    14
13     5     5

我希望比较每组中的第一个得分和最后得分,如果最后得分小于第一个得分,则输出组号。预期的输出应该是:

group 1 3 5

有没有人知道如何实现这个目标?

5 个答案:

答案 0 :(得分:3)

这是data.table方法

library(data.table)
setDT(df)[, score[1] > score[.N], by = group][V1 == TRUE]

##    group   V1
## 1:     1 TRUE
## 2:     3 TRUE
## 3:     5 TRUE

或者

setDT(df)[, group[score[1] > score[.N]], by = group]

##    group V1
## 1:     1  1
## 2:     3  3
## 3:     5  5

或者

setDT(df)[, .BY[score[1] > score[.N]], by = group]

根据@ beginneR的评论,如果您不喜欢V1,那么

df2 <- as.data.table(df)[, .BY[score[1] > score[.N]], by = group][, V1 := NULL]
df2

##    group
## 1:     1
## 2:     3
## 3:     5

答案 1 :(得分:2)

这应该做的工作:

# First split the data frame by group
# This returns a list
df.split <- split(df, factor(df$group))

# Now use sapply on the list to check first and last of each group
# We return the group or NA using ifelse
res <- sapply(df.split, 
       function(x){ifelse(x$score[1] > x$score[nrow(x)], x$group[1], NA)})

# Finally, filter away the NAs
res <- res[!is.na(res)]

答案 2 :(得分:1)

这个答案假定每个小组至少有2个观察结果:

newdf <- merge(rbind(df[diff(df$group) == 1 ,] , df[dim(df)[1], ]), 
           df[!duplicated(df$group), ],
           by="group")

newdf[which(newdf$score.x < newdf$score.y), 'group']
#[1] 1 3 5 

df[diff(df$group) == 1 ,]标识每个组的最后一次观察,最后一组除外,这就是我rbind最后一个条目(即df[dim(df)[1], ])的原因。然后,每组的第一次观察由df[!duplicated(df$group), ]给出。我们将这些组合在组列上,然后确定哪些符合条件。

merge步骤的另一个选项:

merge(df[which(!duplicated(df$group))+(rle(df$group)$lengths-1),],
  df[!duplicated(df$group), ],
  by="group")

答案 3 :(得分:1)

另一个基本R选项:

with(df, unique(df$group[as.logical(ave(score, group, FUN = function(x) head(x,1) > tail(x, 1)))]))
#[1] 1 3 5

或使用dplyr

library(dplyr)
group_by(df, group) %>% filter(first(score) > last(score)) %>% do(head(.,1)) %>% 
 select(group)

#  group
#1     1
#2     3
#3     5

答案 4 :(得分:0)

我是plyr包装乐趣..

library(plyr)
df1<-ddply(df,.(group),summarise,shown=score[length(group)]<score[1])
subset(df1,shown)

group shown
1     TRUE
3     TRUE
5     TRUE