Расчет R в кадре данных с контрольной или базовой группой
У меня есть датафрейм df, который содержит оценки из 2 сайтов (A&B), 2 групп (group1&2) с 3 различными методами (method1, method2, method0):
df1<-data.frame(site=rep("A", 21),
group=rep("group1", 21),
estimate=c(rnorm(10, 15, 3), rnorm(10, 2, 7), rnorm(1, 6, 2)),
method=c(rep(c("method1","method2"),each=10),"method0"))
df2<-data.frame(site=rep("B", 21),
group=rep("group2", 21),
estimate=c(rnorm(10, 13, 3), rnorm(10, 5, 7), rnorm(1, 9, 2)),
method=c(rep(c("method1","method2"),each=10),"method0"))
df<-rbind(df1, df2)
df
site group estimate method
1 A group1 15.1561073 method1
2 A group1 14.4067422 method1
3 A group1 12.7428921 method1
..........
41 B group2 0.3548033 method2
42 B group2 10.5820482 method0
Я хотел бы использовать method0 в качестве базовой группы и рассчитать относительное процентное отклонение (rb) для каждой оценки в каждом сайте / группе.
#for each site and group of estimate
rb<-(estimate-estimate0)/estimate0*100%
# where estimate0 is the estimate of method0 of that certain site/group
и есть ТОЛЬКО ОДНА оценка0 в каждом сайте / группе. Я пытался написать простую функцию и использовать apply
для каждого сайта / группы, но не получилось.
fun.rb<-function(df, basline){
control<-df$method==baseline
rb<-(df$estimate-control$estimate)/(control$estimate)*100%
return(rb)
}
df %>% group_by(site,group) %>% mutate(rb=fun.rb, baseline="method0")
Любой вклад и комментарии с благодарностью.
2 ответа
Вот простой и более элегантный способ того, что вы пытаетесь сделать.
Во-первых, упростите вашу функцию (если вы собираетесь использовать ее в конвейере, ей не нужно принимать весь df в качестве аргумента):
fun.rb <- function(estimate, baseline){
(estimate-baseline)/(baseline)*100
}
Теперь все, что вам нужно сделать, это создать столбец базовой линии, а затем вызвать вашу функцию для каждой строки, передав столбцы оценки и базовой линии вашей функции:
df <- df %>%
group_by(site,group) %>%
mutate(baseline = estimate[method=="method0"], rb = fun.rb(estimate, baseline))
Это может быть не самым элегантным. Я просто взломать Но я думаю, что он делает то, что вы хотите.
> library(dplyr)
> newdf <- df %>% filter(method=="method0") %>%
+ rename(method0_value = estimate) %>%
+ select(-method)
> head(newdf)
site group method0_value
1 A group1 2.529237
2 B group2 7.863411
Этот набор данных будет содержать все ваши базовые / контрольные значения. Следующий фрагмент кода объединяет его с исходным фреймом данных и создает необходимую переменную. Затем вы можете удалить method0_value, если хотите. Это хорошая проверка.
> finaldf <- left_join(df,newdf,by=c("site","group")) %>%
+ mutate(rb= (estimate/method0_value)*100)
> head(finaldf)
site group estimate method method0_value rb
1 A group1 8.928171 method1 2.529237 352.9986
2 A group1 11.171023 method1 2.529237 441.6757
3 A group1 10.790150 method1 2.529237 426.6169
4 A group1 8.990635 method1 2.529237 355.4683
5 A group1 14.813661 method1 2.529237 585.6969
6 A group1 14.518803 method1 2.529237 574.0390
Я знаю, что есть способы сделать это, которые могут быть более эффективными, но я все еще новичок.