在保留所有列信息的情况下,对数据应用group_by和summarise函数。

87

我有一个包含22000行和25列的大数据集。我想按照其中一列对数据进行分组,并在分组后基于另一列取最小值。问题是,这只会给出包含分组列和具有最小值的列的两列结果,而我需要与最小值相关的其他所有列的信息。

这里有一个简单的例子以便复现:

    data<- data.frame(a=1:10, b=c("a","a","a","b","b","c","c","d","d","d"), c=c(1.2, 2.2, 2.4, 1.7, 2.7, 3.1, 3.2, 4.2, 3.3, 2.2), d= c("small", "med", "larg", "larg", "larg", "med", "small", "small", "small", "med"))

    d<- data %>%
    group_by(b) %>%
    summarise(min_values= min(c))
    d
    b min_values
    1 a        1.2
    2 b        1.7
    3 c        3.1
    4 d        2.2

所以,我需要列a和d的相关信息,然而,由于列c中存在值的重复,我无法根据min_value列合并它们... 我想知道在使用dplyr包时是否有保留其他列信息的方法。

我在这里找到了一些解释 "dplyr: group_by, subset and summarise" 和这里 "Finding percentage in a sub-group using group_by and summarise" 但是没有一个能解决我的问题。


您打算让生成的data.frame长成什么样子?当将其他数据压缩为单行时,它们会呈现出什么样子? - r2evans
4个回答

67
您可以在不使用summarize的情况下使用group_by
data %>%
  group_by(b) %>%
  mutate(min_values = min(c)) %>%
  ungroup()

2
非常感谢您,Bergant。问题是您的方法给了我所有的行……但对我来说重要的是知道例如最小值与列“a”中的数字4有关。Docendo在下面的回答正是我所需要的。无论如何,感谢您花时间回答 :-) - Momeneh Foroutan
3
这个答案让我有了“当然”的瞬间。 - Brian D
1
如此简单,却又如此强大。 - Karol Daniluk
@bergant,这对我没有用,即使我包括了ungroup(),在我汇总后结果仍然只显示2列。 - Katya
1
应该用slice(1)代替ungroup(),这将减少每个组的行数,并且也可以与多个摘要列一起使用。 - Aaron C

61

以下是两种使用dplyr的选项: a) filter 和 b) slice。在这种情况下,对于任何一个组中的列c,都没有重复的最小值,因此a)和b)的结果相同。如果存在重复的最小值,则方法a)会返回每个组的每个最小值,而方法b)只会返回每个组中的一个最小值(第一个)。

b)

> data %>% group_by(b) %>% filter(c == min(c))
#Source: local data frame [4 x 4]
#Groups: b
#
#   a b   c     d
#1  1 a 1.2 small
#2  4 b 1.7  larg
#3  6 c 3.1   med
#4 10 d 2.2   med

或类似地

> data %>% group_by(b) %>% filter(min_rank(c) == 1L)
#Source: local data frame [4 x 4]
#Groups: b
#
#   a b   c     d
#1  1 a 1.2 small
#2  4 b 1.7  larg
#3  6 c 3.1   med
#4 10 d 2.2   med

b)

->

b)

> data %>% group_by(b) %>% slice(which.min(c))
#Source: local data frame [4 x 4]
#Groups: b
#
#   a b   c     d
#1  1 a 1.2 small
#2  4 b 1.7  larg
#3  6 c 3.1   med
#4 10 d 2.2   med

3
非常感谢 Docendo 的回答。这正是我在寻找的 :-) - Momeneh Foroutan
正是我所需要的!而且我还额外发现了切片函数,谢谢! - Aditya
3
如果你尝试使用总结来获取原始数据中没有包含的信息,因此无法进行“筛选”,例如求和或平均值,该怎么办? - canderson156
虽然来晚了,但你仍然可以通过函数的返回值进行筛选。例如,你可以执行 df %>% group_by(x) %>% filter(n() > 10) 来过滤具有超过十个观测值的组,而无需将 n() 分配给任何先前的列。 - mhovd

3
使用 sqldf
library(sqldf)
 # Two options:
sqldf('SELECT * FROM data GROUP BY b HAVING min(c)')
sqldf('SELECT a, b, min(c) min, d FROM data GROUP BY b')

输出:

   a b   c     d
1  1 a 1.2 small
2  4 b 1.7  larg
3  6 c 3.1   med
4 10 d 2.2   med

1

dplyr 1.1.0 中,您可以在 mutatesummarizefilterslice 中使用 .by 进行临时分组。使用 mutate 时,所有行和列都会被保留:

data %>% 
  mutate(min_values = min(c), .by = b)

使用 filter 或者 slice,可以对行进行汇总并保留所有列:

data %>% 
  slice_min(c, .by = b)

data %>% 
  filter(c = min(c), .by = b)

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