2016-10-25 10 views
1

У меня есть dataframe df, который содержит оценки из 2-х сайтов (A & B), 2 группы (group1 & 2) с тремя различными методами (метод1, метод2, метод0):Расчет R в кадре данных с группой управления или базовой линией

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 в качестве базовой группы и вычислить относительное процентное смещение (РБ) для каждой оценки на каждом участке/группе.

#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") 

Любые ввод и комментарии с благодарностью.

ответ

1

Вот простой и элегантный способ того, что вы пытаетесь сделать.

Во-первых, упростить функцию (если your'e будет использовать его в трубе, не нужно брать весь ФР в качестве аргумента):

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)) 
+0

Ничего себе, он отлично выглядит. Спасибо за исправление моей функции. – lamushidi

+0

Я должен указать, что вам действительно не нужна эта функция, и вы можете сделать все, что нужно встроить, заменив вызов функции вычислением внутри функции. – yeedle

+0

да, конечно. Это сделает коды еще более аккуратными. Большое спасибо. – lamushidi

1

Это может быть не самый элегантный. Я просто взломал. Но я думаю, что он делает то, что вы хотите.

> 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 

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

+0

Большое спасибо. Это довольно интуитивно понятно и на самом деле занимает всего две строки кодов. Плюс это не требует написания функции, которая великолепна. – lamushidi