在dplyr中,使用字符串向量输入可以按多个列进行分组。
在dplyr中,使用字符串向量输入可以按多个列进行分组。
我正在尝试将我对plyr的理解转换到dplyr中,但我无法弄清楚如何按多列进行分组。\n
# 使用无法硬编码的奇怪列名创建数据 data = data.frame( asihckhdoydkhxiydfgfTgdsx = sample(LETTERS[1:3], 100, replace=TRUE), a30mvxigxkghc5cdsvxvyv0ja = sample(LETTERS[1:3], 100, replace=TRUE), value = rnorm(100) ) # 获取我们想要在其中求平均值的列 columns = names(data)[-3] # plyr - 可行 ddply(data, columns, summarize, value=mean(value)) # dplyr - 报错 data %.% group_by(columns) %.% summarise(Value = mean(value)) #> Error in eval(expr, envir, enclos) : index out of bounds
\n我在将plyr示例转换为dplyr风格的语法时漏掉了什么?
问题:在dplyr中如何按多个列进行分组?
问题的原因:在使用dplyr进行数据处理时,有时需要按多个列进行分组。然而,在早期的版本中,dplyr的group_by函数只能按单个列进行分组,无法满足用户的需求。
解决方法:为了解决这个问题,dplyr在后续的版本中添加了scoped版本的group_by函数。这个函数可以接受一个字符串向量作为输入,实现按多个列进行分组的功能。使用这个函数的方法如下:
data = data.frame( asihckhdoydkhxiydfgfTgdsx = sample(LETTERS[1:3], 100, replace=TRUE), a30mvxigxkghc5cdsvxvyv0ja = sample(LETTERS[1:3], 100, replace=TRUE), value = rnorm(100) ) # get the columns we want to average within columns = names(data)[-3] library(dplyr) df1 <- data %>% group_by_at(vars(one_of(columns))) %>% summarize(Value = mean(value))
这样就可以按columns中指定的多个列对data进行分组,并计算每组的value列的平均值。与此同时,为了验证结果的正确性,还可以使用plyr包中的ddply函数进行比较,代码如下:
df2 <- plyr::ddply(data, columns, plyr::summarize, value=mean(value)) table(df1 == df2, useNA = 'ifany')
可以看到,通过比较df1和df2的结果,可以发现它们是相同的。
需要注意的是,由于dplyr的summarize函数只能去掉一层分组,所以在df1的结果中仍然存在一层分组。为了完全去除这一层分组,可以在summarize后面加上%>% ungroup代码。
除了使用group_by_at函数,还可以使用group_by函数的.dots参数来实现按多个列进行分组,如下所示:
data %>% group_by(.dots = columns) %>% summarize(value = mean(value))
在这种方式下,使用.dots参数来指定要按哪些列进行分组。
另外,对于问题“如何在多个列上计算平均值”,可以使用select语法中的新函数across来实现。具体使用方法可以参考dplyr的官方文档(https://dplyr.tidyverse.org/reference/across.html)。例如,如果想要计算value_A和value_B列的平均值,可以使用下面的代码:
summarize(across(all_of(c('value_A', 'value_B')), mean))
通过这种方式,可以方便地在多个列上应用函数进行计算。
问题的出现原因是想要使用dplyr包中的group_by函数按照多个列进行分组,但是要求输入的分组列是一个字符串向量,而不是硬编码的列名。在给出的代码中,虽然使用了lapply函数将字符串向量转换为符号列表,但仍然需要在group_by函数中使用.dots参数来指定分组列。
解决方法是使用lapply函数将字符串向量转换为符号列表,并将该列表作为.dots参数传递给group_by函数。具体的实现代码如下:
library(dplyr) df <- data.frame( asihckhdoydk = sample(LETTERS[1:3], 100, replace=TRUE), a30mvxigxkgh = sample(LETTERS[1:3], 100, replace=TRUE), value = rnorm(100) ) # Columns you want to group by grp_cols <- names(df)[-3] # Convert character vector to list of symbols dots <- lapply(grp_cols, as.symbol) # Perform frequency counts df %>% group_by_(.dots=dots) %>% summarise(n = n())
运行上述代码后,可以得到按照两个列进行分组的结果。输出结果如下:
Source: local data frame [9 x 3] Groups: asihckhdoydk asihckhdoydk a30mvxigxkgh n 1 A A 10 2 A B 10 3 A C 13 4 B A 14 5 B B 10 6 B C 12 7 C A 9 8 C B 12 9 C C 10
通过这种方法,可以实现按照字符串向量指定的多个列进行分组的功能。