(以下情况简化了我的实际情况)
我的数据来自村庄,我想按村庄变量来总结结果变量。
> data
village A Z Y
<chr> <int> <int> <dbl>
1 a 1 1 500
2 a 1 1 400
3 a 1 0 800
4 b 1 0 300
5 b 1 1 700
例如,我只想通过村庄使用Y
来计算Z==z
的平均值。在这种情况下,我想让(a)村庄有(500 + 400)/ 2 = 450,而让“ b”村庄有700。
请注意,实际情况更为复杂,我无法直接使用this answer,但是关键是我需要将分组的小节和全局变量(z)传递给函数 >。
z <- 1 # z takes 0 or 1
data %>%
group_by(village) %>% # grouping by village
summarize(Y_village = Y_hat_village(., z)) # pass a part of tibble and a global variable
Y_hat_village <- function(data_village, z){
# This function takes a part of tibble (`data_village`) and a variable `z`
# Calculate the mean for a specific z in a village
data_z <- data_village %>% filter(Z==get("z"))
return(mean(data_z$Y))
}
但是,我发现.
传递了整个小标题,并且上面的代码为所有组返回了相同的值。
答案 0 :(得分:4)
您可以简化两件事。其中之一就是您的函数:由于您要向函数传递值z
,因此无需使用get("z")
。您在传入的全局环境中有一个z
;或者,更安全地,将z值分配给其他名称的变量,这样您就不会遇到范围问题,并将其传递给函数。在这种情况下,我称其为z_val
。
library(tidyverse)
z_val <- 1
Y_hat_village2 <- function(data, z) {
data_z <- data %>% filter(Z == z)
return(mean(data_z$Y))
}
您可以使用do
在每个组上进行函数调用,这将为您提供一个列表列,然后取消嵌套该列。再次注意,我正在将变量z_val
传递给参数z
。
df %>%
group_by(village) %>%
do(y_hat = Y_hat_village2(., z = z_val)) %>%
unnest()
#> # A tibble: 2 x 2
#> village y_hat
#> <chr> <dbl>
#> 1 a 450
#> 2 b 700
但是,do
被弃用,而赞成purrr::map
,我仍然难以摆脱困境。在这种情况下,您可以分组并嵌套,这将提供一列称为data
的数据帧,然后映射到该列并再次提供z = z_val
。当您取消嵌套y_hat
列的嵌套时,您仍将原始数据作为嵌套列,因为您仍想访问其余的列。
df %>%
group_by(village) %>%
nest() %>%
mutate(y_hat = map(data, ~Y_hat_village2(., z = z_val))) %>%
unnest(y_hat)
#> # A tibble: 2 x 3
#> village data y_hat
#> <chr> <list> <dbl>
#> 1 a <tibble [3 × 3]> 450
#> 2 b <tibble [2 × 3]> 700
只是为了检查一切是否正常,我还传递了z = 0
来检查1.范围问题,以及2. z的其他值是否起作用。
df %>%
group_by(village) %>%
nest() %>%
mutate(y_hat = map(data, ~Y_hat_village2(., z = 0))) %>%
unnest(y_hat)
#> # A tibble: 2 x 3
#> village data y_hat
#> <chr> <list> <dbl>
#> 1 a <tibble [3 × 3]> 800
#> 2 b <tibble [2 × 3]> 300
答案 1 :(得分:1)
作为@patL答案的扩展/修改,您还可以将tidyverse
解决方案包装在purrr:map
中,以返回两个list
的{{1}},每一个{ tibble
值:
z
z <- c(0, 1);
map(z, ~df %>% filter(Z == .x) %>% group_by(village) %>% summarise(Y.mean = mean(Y)))
#[[1]]
## A tibble: 2 x 2
# village Y.mean
# <fct> <dbl>
#1 a 800.
#2 b 300.
#
#[[2]]
## A tibble: 2 x 2
# village Y.mean
# <fct> <dbl>
#1 a 450.
#2 b 700.
答案 2 :(得分:0)
您可以使用dplyr
来完成它:
library(dplyr)
df %>%
group_by(village) %>%
filter(Z == 1) %>%
summarise(Y_village = mean(Y))
## A tibble: 2 x 2
# village Y_village
# <chr> <dbl>
#1 a 450
#2 b 700
要获取所有列:
df %>%
group_by(village) %>%
filter(Z == 1) %>%
mutate(Y_village = mean(Y)) %>%
distinct(village, A, Z, Y_village)
## A tibble: 2 x 4
## Groups: village [2]
# village A Z Y_village
# <chr> <dbl> <dbl> <dbl>
#1 a 1 1 450
#2 b 1 1 700
df <- data_frame(village = c("a", "a", "a", "b", "b"),
A = rep(1, 5),
Z = c(1, 1, 0, 0, 1),
Y = c(500, 400, 800, 30, 700))