Расчет 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

Я знаю, что есть способы сделать это, которые могут быть более эффективными, но я все еще новичок.

Другие вопросы по тегам