r - 管理 dplyr group_by 函数以在与 group_modify 结合使用时保留分组变量
问题描述
我正在尝试使用该功能(我在这里group_modify
了解到)。
目标是取 a data.frame
,将其拆分,group_by
然后应用自制函数进行一些重组(即排序,选择“最佳行”,如果超过一个,则平均值)。我需要输出data.frame
包含原始列的所有列。
这是一个可以让一切变得更清晰的 RE:
数据:
library(dplyr)
(dd <- data.frame(id = c("a", "a", "b", "b", "c", "c", "c"), cat = c("s2", "s1", "s1", "s1", "s3", "s2", "s2"), val = 1:7))
id cat val
1 a s2 1
2 a s1 2
3 b s1 3
4 b s1 4
5 c s3 5
6 c s2 6
7 c s2 7
我的功能(显示我的问题的基本功能,但不完全是我实际使用的功能):
simple_fun <- function(slice, key){
big_out_to_show_error <<- slice
temp1 <- arrange(slice, cat)
temp2 <- temp1 %>%
filter(cat==temp1$cat[1])
if(nrow(temp2)>1) {
temp2 <- temp2 %>%
group_by(id, cat) %>%
summarise(val = mean(val))
}
return(data.frame(temp2))
}
我想要的输出(每个 ID 一行具有“最佳” cat
,如果多于一行,则为原始变量的平均值val
和所有data.frame
变量):
id cat val
a a s1 2.0
b b s1 3.5
c c s2 6.5
我尝试使用dplyr::group_modify
函数会引发错误:
dd %>%
group_by(id) %>%
group_modify(simple_fun)
Show Traceback
Rerun with Debug
Error: Column `id` is unknown
这是因为slice
使用的 不包括分组变量。从这个简单的代码可以看出这一点,它使用big_out_to_show_error <<- slice
main 函数中的行并限制为id=="a"
:
filter(dd, id=="a") %>%
group_by(id) %>%
group_modify(simple_fun)
# A tibble: 1 x 3
# Groups: id [1]
id cat val
<fct> <fct> <int>
1 a s1 2
big_out_to_show_error
# A tibble: 2 x 2
cat val
<fct> <int>
1 s2 1
2 s1 2
如何管理group_by
函数以仍然在切片中抛出分组变量,以便我的函数可以使用group_modify
?
作为旁注,我真的在尝试理解和修复这种dplyr
group_by
行为。我已经知道基本的 R 方法:
split(dd, dd$id) %>%
lapply(simple_fun) %>%
do.call("rbind", .)
id cat val
a a s1 2.0
b b s1 3.5
c c s2 6.5
谢谢
解决方案
group_modify()
为每个组创建两个对象 - 一个包含子集数据的小标题,以及一个包含组信息的单独的单行小标题。
因为返回数据时会自动恢复组信息group_modify()
,所以一般不需要将这些信息保留在子集数据中,默认情况下是去掉的。但是,您可以使用.keep
参数来保留它,但是如果在您的函数返回数据时存在组变量,这将导致错误。
因此,您可以通过使用参数来修复您的函数.keep
,然后在返回数据之前删除分组变量:
simple_fun <- function(slice, key){
temp1 <- arrange(slice, cat)
temp2 <- temp1 %>%
filter(cat==temp1$cat[1])
if(nrow(temp2)>1) {
temp2 <- temp2 %>%
group_by(id, cat) %>%
summarise(val = mean(val), .groups = "drop")
}
temp2 %>%
select(-id)
}
dd %>%
group_by(id) %>%
group_modify(simple_fun, .keep = TRUE)
# A tibble: 3 x 3
# Groups: id [3]
id cat val
<chr> <chr> <dbl>
1 a s1 2
2 b s1 3.5
3 c s2 6.5
您还可以简化函数以完全回避这个问题:
simple_fun2 <- function(slice, key){
slice %>%
slice_min(cat, 1) %>%
summarise(cat = unique(cat),
val = mean(val))
}
dd %>%
group_by(id) %>%
group_modify(simple_fun2)
# A tibble: 3 x 3
# Groups: id [3]
id cat val
<chr> <chr> <dbl>
1 a s1 2
2 b s1 3.5
3 c s2 6.5
推荐阅读
- magento - magento 1.7 缺少左侧客户帐户导航
- machine-learning - MxNet 无法保存网络的所有参数
- javascript - 如何从数据数组(JS)中删除特定列
- spring-boot-admin - Spring Boot Admin Client 未注册应用程序
- python-3.x - 熊猫如何在月底前获得n天的日期
- java - 在 ArrayList INSIDE Stack 中搜索元素
- c# - 使用 C# .NET 将 PDF 转换为 Excel
- javascript - 如何在使用 vue.js 单击按钮后禁用按钮
- python - 命令冷却数小时和数分钟
- indexeddb - NotFoundError : DOM IDVDatabase Exception 8 - 在 ipad 上使用 dexie 时(在桌面 chrome 和 safari 上工作))