使用带过滤器的dplyr,group_by&尾巴?

时间:2014-07-01 14:32:06

标签: r dplyr

这是一个例子df:

df <- structure(list(x = 1:30, y = 101:130, g = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L), .Label = c("A", "B", "C"), class = "factor")), .Names = c("x", "y", "g"), row.names = c(NA, -30L), class = "data.frame")

我想在过滤后的数据中获得每组10个最低y值。

但是

df2 <- df %>% filter(x>3) %>% group_by(g) %>%  tail(y, n=10)

仅返回最后一组的行(在本例中为C):

Source: local data frame [10 x 3]
Groups: g

    x   y g
18 21 121 C
19 22 122 C
20 23 123 C
21 24 124 C
22 25 125 C
23 26 126 C
24 27 127 C
25 28 128 C
26 29 129 C
27 30 130 C

我做错了什么?

6 个答案:

答案 0 :(得分:17)

您可以在tail内使用do

df2 <- df %>% filter(x>3) %>% group_by(g) %>%  do(tail(., n=10))

使用.是实现这一目标的关键。从do帮助页面:&#34;您可以使用。引用当前组。&#34;

编辑:

正如@beginneR所指出的那样,我专注于如何在tail的群组中使用dplyr并错过了OP要求10 最低 y的值。要正确执行此操作,需要添加arrange。对于tail,这意味着按y的降序排列。

df2 <- df %>% filter(x>3) %>% group_by(g) %>%  arrange(desc(y)) %>% do(tail(., n=10))

答案 1 :(得分:4)

以下是另外两个选项:

df %>% filter(x>3) %>% group_by(g) %>% top_n(3, desc(y))

我们在这里使用top_n但使用desc(y),因为我们希望最低 y值而不是最大值(“top”){{1值。

y

等于

df %>% filter(x>3) %>% group_by(g) %>% arrange(y) %>% filter(1:n() <= 10)

分组后,我们通过增加df %>% filter(x>3) %>% group_by(g) %>% arrange(y) %>% slice(1:10) 对每个组进行排序,然后选择每组的前10行(如果组中没有10行,则选择更少的行)。

由于对于要选择的最低和最后一个值存在一些混淆:此答案选择最低值,而不是最后一个条目。

答案 2 :(得分:2)

莫尔答案!对于计算排名的“窗口函数”之一,这是一个很好的工作。

df %>%
  filter(x > 3) %>%
  group_by(g) %>%
  filter(y %>% min_rank <= 10)

答案 3 :(得分:1)

我不知道为什么tail无效,但您可以尝试这样做:

df %>% 
 filter(x > 3) %>% 
 group_by(g) %>% 
 filter(.,rank(desc(y),ties.method = "min") <= 10)

答案 4 :(得分:1)

通过data.table更简洁的语法:

library(data.table)
dt = as.data.table(df)

# original tail question
dt[x > 3, tail(y, 10), by = g]

# 10 smallest values of y
# many options for this, here's one:
dt[x > 3, head(sort(y), 10), by = g]

# here's another, trying to take advantage of setkey speed
setkey(dt, g, y)
dt[x > 3, head(y, 10), by = g]

答案 5 :(得分:0)

为什么尾部应该使用分组数据框?它不了解群体。

添加订单列,按该列选择,删除该列。这里我使用3而不是10来表示紧凑性(和%。%因为旧版本的dplyr):

> df %.% filter(x>3) %.% group_by(g) %.% mutate(i=order(y)) %.% filter(i <= 3) %.% select(-matches("i"))
Source: local data frame [9 x 3]
Groups: g

   x   y g
1  4 104 A
2  5 105 A
3  6 106 A
4 11 111 B
5 12 112 B
6 13 113 B
7 21 121 C
8 22 122 C
9 23 123 C