如何使用summarize_at
实现此目的?
数据:
library(dplyr)
set.seed(100)
test_df <- data.frame(var_name=c(rep(LETTERS[1:3],each=3),"C"),
group_name=c(1,1,0,0,1,0,1,1,1,1),
obs_1=rnorm(10),
obs_2=rnorm(10))
我想要实现的目标:
test_df %>%
group_by(var_name) %>%
summarise(delta_obs1 = median(obs_1[group_name==1])-median(obs_1[group_name==0]),
delta_obs2 = median(obs_2[group_name==1])-median(obs_2[group_name==0]),
n_group1 = length(which(group_name==0)),
n_group0 = length(which(group_name==1)))
# A tibble: 3 x 5
var_name delta_obs1 delta_obs2 n_group1 n_group0
<fctr> <dbl> <dbl> <int> <int>
1 A -0.1064135 0.2947143 1 2
2 B -0.4857362 -0.2318824 2 1
3 C NA NA 0 4
然而,如果有很多列(如我的实际情况),这是相当混乱和乏味的。
我无法使用的summarize_at
版本:
fun_obs_median <-
function(x) {
median(x[.$group_name == 1]) - median(x[.$group_name == 0])
}
test_df %>%
group_by(var_name) %>%
summarize_at(.vars = colnames(.)[3:4],
.funs=fun_obs_median)
Error in summarise_impl(.data, dots) : Evaluation error: object '.' not found.
答案 0 :(得分:1)
这会有所帮助:
library(tidyverse)
set.seed(100)
test_df <- data.frame(var_name=c(rep(LETTERS[1:3],each=3),"C"),
group_name=c(1,1,0,0,1,0,1,1,1,1),
obs_1=rnorm(10),
obs_2=rnorm(10))
# function to calculate delta
delta_f = function(x) x[2]-x[1]
test_df %>%
group_by(var_name, group_name) %>% # for each combination of var and group
summarise_at(vars(matches("obs")), median) %>% # get the median for all columns that match "obs"
arrange(var_name, group_name) %>% # for each var get group == 0 in first row and group == 1 in second row
summarise_at(vars(matches("obs")), funs(delta = delta_f)) # apply delta function
# # A tibble: 3 x 3
# var_name obs_1_delta obs_2_delta
# <fct> <dbl> <dbl>
# 1 A -0.106 0.295
# 2 B -0.486 -0.232
# 3 C NA NA
看起来arrange()
部分不是必需的,因为分组会按照您想要的方式自动排序。但是,如果由于软件包更新导致将来行为发生变化,那么保持这种情况会很好。
对于计数,您可以使用此
test_df %>%
mutate(group_name = paste0("n_group", group_name)) %>%
count(var_name, group_name) %>%
spread(group_name, n, fill = 0)
# # A tibble: 3 x 3
# var_name n_group0 n_group1
# <fct> <dbl> <dbl>
# 1 A 1 2
# 2 B 2 1
# 3 C 0 4
然后按var_name
加入两个表。