使用最大值对数据框进行子集/分组?

3

给定这样的数据框:

  gid set  a  b
1   1   1  1  9
2   1   2 -2 -3
3   1   3  5  6
4   2   2 -4 -7
5   2   6  5 10
6   2   9  2  0

如何对唯一的gid数据帧进行子集/分组,并且使用最大的set值和1/0来确定其a值是否大于其b值?

因此,在这里,它应该是...

1,3,0
2,9,1

在SQL中,这是一件相当简单的事情,但我希望更好地控制我的R。因此...

3个回答

6

使用dplyr非常简单:

dat <- read.table(text="gid set  a  b
1   1  1  9
1   2 -2 -3
1   3  5  6
2   2 -4 -7
2   6  5 10
2   9  2  0", header=TRUE)

library(dplyr)

dat %>%
  group_by(gid) %>%
  filter(row_number() == which.max(set)) %>%
  mutate(greater=a>b) %>%
  select(gid, set, greater)

## Source: local data frame [2 x 3]
## Groups: gid
## 
##   gid set greater
## 1   1   3   FALSE
## 2   2   9    TRUE

如果你真的需要1和0,并且dplyr的分组引起任何不安:

dat %>%
  group_by(gid) %>%
  filter(row_number() == which.max(set)) %>%
  mutate(greater=ifelse(a>b, 1, 0)) %>%
  select(gid, set, greater) %>%
  ungroup

## Source: local data frame [2 x 3]
## 
##   gid set greater
## 1   1   3       0
## 2   2   9       1

您可以不使用管道来完成相同的操作:

ungroup(
  select(
    mutate(
      filter(row_number() == which.max(set)), 
      greater=ifelse(a>b, 1, 0)), gid, set, greater))

但是……但是……为什么呢?! :-)

这是一个相当流行的“管道”习语,最初由magrittr包开始使用,但在“Hadleyverse”(即dplyrggvistidyr等)中广泛使用。与复杂的嵌套括号不同,这个习语将数据“管道”到函数进行处理,类似于D3 JavaScript函数链的工作方式。 - hrbrmstr
感谢提供详细信息! - Wells
1
如果集合中存在最大值的并列情况,这可能会有问题。使用 filter(row_number() == which.max(set)) 可能更安全。 - Rich Scriven
你如何按照例如集合编号升序排序结果? - Wells
此外,这个%>%似乎最多只能显示十个项目,然后我会得到一行.. ... ...,看起来表示还有更多?为什么会有这种限制,我该如何避免它? - Wells
显示剩余4条评论

3

这里有一个 data.table 的可能性,假设你的原始数据称为 df

library(data.table)

setDT(df)[, .(set = max(set), b = as.integer(a > b)[set == max(set)]), gid]
#    gid set b
# 1:   1   3 0
# 2:   2   9 1

请注意,为了解决多个max(set)行的问题,我使用set == max(set)作为子集,以便对于与最大值相同的行数返回相同的行数(如果这有任何意义的话)。
还有一种数据表选项,由@thelatemail提供。
setDT(df)[, list(set = max(set), ab = (a > b)[which.max(set)] + 0), by = gid]
#    gid set ab
# 1:   1   3  0
# 2:   2   9  1

1
在基础 R 中,您可以使用 ave。
indx <- with(df, ave(set, gid, FUN=max)==set)
#in cases of ties
#indx <- with(df, !!ave(set, gid, FUN=function(x) 
#                  which.max(x) ==seq_along(x)))


transform(df[indx,], greater=(a>b)+0)[,c(1:2,5)]
#   gid set greater
# 3   1   3       0
# 6   2   9       1

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