dplyr:将分组的小标题传递给自定义函数

use*_*524 6 r dplyr

(以下场景简化了我的实际情况)
我的数据来自村庄,我想通过一个村庄变量来总结一个结果变量。

> 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  
Run Code Online (Sandbox Code Playgroud)

例如,我想计算YZ==z由村庄使用的平均值。在这种情况下,我希望村庄“a”为 (500 + 400)/2 = 450,村庄“b”为 700。

请注意,实际情况更复杂,我不能直接使用这个答案,但重点是我需要将分组的 tibble 和全局变量 (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))
}
Run Code Online (Sandbox Code Playgroud)

但是,我发现.传递整个 tibble 并且上面的代码为所有组返回相同的值。

cam*_*lle 6

您可以简化一些事情。一是在您的函数中:由于您正在z向函数传递一个值,因此您不需要使用get("z"). 你有一个z你传入的全局环境;或者,更安全的是,将 z 值分配给具有其他名称的变量,这样就不会遇到范围问题,并将其传递给函数。在本例中,我将其称为z_val.

\n\n\n\n
library(tidyverse)\n\nz_val <- 1\n\nY_hat_village2 <- function(data, z) {\n  data_z <- data %>% filter(Z == z)\n  return(mean(data_z$Y))\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

您可以使用 对每个组进行函数调用do,这将为您提供一个列表列,然后取消该列的嵌套。再次注意,我将变量传递z_val给参数z

\n\n
df %>%\n  group_by(village) %>%\n  do(y_hat = Y_hat_village2(., z = z_val)) %>%\n  unnest()\n#> # A tibble: 2 x 2\n#>   village y_hat\n#>   <chr>   <dbl>\n#> 1 a         450\n#> 2 b         700\n
Run Code Online (Sandbox Code Playgroud)\n\n

然而,do已被弃用purrr::map,取而代之的是 ,我仍然无法掌握窍门。在这种情况下,您可以分组和嵌套,这会给出一列名为 的数据框data,然后映射该列并再次提供z = z_val。当您取消y_hat嵌套列时,您仍然拥有作为嵌套列的原始数据,因为您仍然希望访问其余列。

\n\n
df %>%\n  group_by(village) %>%\n  nest() %>%\n  mutate(y_hat = map(data, ~Y_hat_village2(., z = z_val))) %>%\n  unnest(y_hat)\n#> # A tibble: 2 x 3\n#>   village data             y_hat\n#>   <chr>   <list>           <dbl>\n#> 1 a       <tibble [3 \xc3\x97 3]>   450\n#> 2 b       <tibble [2 \xc3\x97 3]>   700\n
Run Code Online (Sandbox Code Playgroud)\n\n

为了检查一切是否正常,我还检查了z = 01. 范围问题,以及 2. z 的其他值是否有效。

\n\n
df %>%\n  group_by(village) %>%\n  nest() %>%\n  mutate(y_hat = map(data, ~Y_hat_village2(., z = 0))) %>%\n  unnest(y_hat)\n#> # A tibble: 2 x 3\n#>   village data             y_hat\n#>   <chr>   <list>           <dbl>\n#> 1 a       <tibble [3 \xc3\x97 3]>   800\n#> 2 b       <tibble [2 \xc3\x97 3]>   300\n
Run Code Online (Sandbox Code Playgroud)\n