Как написать функцию, которая проводит парные t-тесты для всех комбинаций группы / переменной в кадре данных - PullRequest
0 голосов
/ 23 января 2020

У меня есть кадр данных, похожий на data, созданный ниже:

ID <- data.frame(ID=rep(c(12,122,242,329,595,130,145,245,654,878),each=5))
Var <- data.frame(Variable=c("Copper","Iron","Lead","Zinc","CaCO"))
n <- 10
Variable <- do.call("rbind",replicate(n,Var,simplify=F))
Location <- rep(c("Alpha","Beta","Gamma"), times=c(20,20,10))
Location <- data.frame(Location)
set.seed(1)
FirstPt<- data.frame(FirstPt=sample(1:100,50,replace=T))
LastPt <- data.frame(LastPt=sample(1:100,50,replace=T))
First3<- data.frame(First3=sample(1:100,50,replace=T))
First5<- data.frame(First5=sample(1:100,50,replace=T))
First7<- data.frame(First7=sample(1:100,50,replace=T))
First10<- data.frame(First10=sample(1:100,50,replace=T))
Last3<- data.frame(Last3=sample(1:100,50,replace=T))
Last5<- data.frame(Last5=sample(1:100,50,replace=T))
Last7<- data.frame(Last7=sample(1:100,50,replace=T))
Last10<- data.frame(Last10=sample(1:100,50,replace=T))
data <- cbind(ID,Location,Variable,FirstPt,LastPt,First3,First5,First7,
              First10,Last3,Last5,Last7,Last10)

Это может быть вопрос из двух частей, но я хочу написать функцию, которая группирует все одинаковые Variables (например, все наблюдения, которые Copper) и проводят парный t-тест между всеми возможными комбинациями столбцов цифры c (FirstPt: Last10). Я хочу, чтобы он возвращал значения p во фрейме данных следующим образом:

Test                        P-Value
FirstPt.vs.LastPt             …
FirstPt.vs.First3             … 
ect...                        … 

Вероятно, это будет вторая функция, но я также хочу сделать это после того, как наблюдения сгруппированы по Location, чтобы кадр выходных данных будет выглядеть так:

Test                                   P-Value
FirstPt.vs.LastPt.InAlpha
FirstPt.vs.LastPt.InBeta        
ect... 

Ответы [ 3 ]

0 голосов
/ 23 января 2020

Вероятно, вы можете получить то, что вы хотите, используя следующий код:

library(dplyr)
library(tidyr)

data %>%
  pivot_longer(cols = FirstPt:Last10) %>%
  group_by(Variable) %>%
  summarise(p_value = list(combn(name, 2, function(x) 
                       t.test(value[name == x[1]], value[name == x[2]])$p.value)), 
            test = list(combn(name, 2, paste, collapse = "_"))) %>%
  unnest(cols = c(test, p_value))


#  Variable p_value test           
#   <fct>      <dbl> <chr>          
# 1 CaCO       0.915 FirstPt_LastPt 
# 2 CaCO       0.529 FirstPt_First3 
# 3 CaCO       0.337 FirstPt_First5 
# 4 CaCO       0.350 FirstPt_First7 
# 5 CaCO       0.395 FirstPt_First10
# 6 CaCO       0.765 FirstPt_Last3  
# 7 CaCO       0.204 FirstPt_Last5  
# 8 CaCO       0.873 FirstPt_Last7  
# 9 CaCO       0.479 FirstPt_Last10 
#10 CaCO       1     FirstPt_FirstPt
# … with 24,740 more rows

Чтобы сделать это сгруппированным по Location, вы можете добавить это в команду group_by и сохранить оставшуюся часть кода в виде является.

0 голосов
/ 23 января 2020

Вы можете выполнить оба этих действия с помощью одной функции:

library(tidyverse)

t.test.by.group.combos <- function(.data, groups){
  by <-  gsub(x = rlang::quo_get_expr(enquo(groups)), pattern = "\\((.*)?\\)", replacement = "\\1")[-1]
  .data %>%
    group_by(!!!groups) %>%
    select_if(is.integer) %>%
    group_split() %>%
    map(.,
      ~pivot_longer(., cols = (FirstPt:Last10), names_to = "name", values_to = "val") %>%
        nest(data = val) %>%
        full_join(.,.,by = by) %>%
        filter(name.x != name.y) %>%
        mutate(test = paste(name.x, "vs",name.y, !!!groups, sep = "."),
               p.value = map2_dbl(data.x,data.y, ~t.test(unlist(.x), unlist(.y))$p.value)) %>%
        select(test,p.value)%>%
      filter(!duplicated(p.value))
    ) %>%
    bind_rows() 
}


t.test.by.group.combos(data, vars(Variable))
#> # A tibble: 225 x 2
#>    test                    p.value
#>    <chr>                     <dbl>
#>  1 FirstPt.vs.LastPt.CaCO    0.511
#>  2 FirstPt.vs.First3.CaCO    0.184
#>  3 FirstPt.vs.First5.CaCO    0.494
#>  4 FirstPt.vs.First7.CaCO    0.354
#>  5 FirstPt.vs.First10.CaCO   0.893
#>  6 FirstPt.vs.Last3.CaCO     0.496
#>  7 FirstPt.vs.Last5.CaCO     0.909
#>  8 FirstPt.vs.Last7.CaCO     0.439
#>  9 FirstPt.vs.Last10.CaCO    0.146
#> 10 LastPt.vs.First3.CaCO     0.578
#> # … with 215 more rows

t.test.by.group.combos(data, vars(Variable, Location))
#> # A tibble: 674 x 2
#>    test                          p.value
#>    <chr>                           <dbl>
#>  1 FirstPt.vs.LastPt.CaCO.Alpha    0.850
#>  2 FirstPt.vs.First3.CaCO.Alpha    0.822
#>  3 FirstPt.vs.First5.CaCO.Alpha    0.895
#>  4 FirstPt.vs.First7.CaCO.Alpha    0.810
#>  5 FirstPt.vs.First10.CaCO.Alpha   0.645
#>  6 FirstPt.vs.Last3.CaCO.Alpha     0.870
#>  7 FirstPt.vs.Last5.CaCO.Alpha     0.465
#>  8 FirstPt.vs.Last7.CaCO.Alpha     0.115
#>  9 FirstPt.vs.Last10.CaCO.Alpha    0.474
#> 10 LastPt.vs.First3.CaCO.Alpha     0.991
#> # … with 664 more rows

Это довольно длинная функция, но обычно мы группируем по аргументу groups, затем выбираем группы и любое целое число. столбцы, затем мы разделяем фрейм данных по группам. После этого мы сопоставляем все комбинации переменных и проводим t.tests для каждой комбинации. Наконец, мы объединяем все группы в один фрейм данных.

0 голосов
/ 23 января 2020

Я думаю, это то, что вы хотите. Ключ должен был использовать group_by и сделать из tidyverse.

df <- NULL
for(i in (4:(ncol(data)-1))){
  for(j in ((i+1):ncol(data))){
    df <- rbind(df,data %>% 
                  group_by(Location) %>% 
                  do(data.frame(pval = t.test(.[[i]],.[[j]], data = .)$p.value)) %>% 
                  ungroup() %>% 
                  mutate(Test = paste0(colnames(data)[i],'.vs.',colnames(data)[j]))
                )
  }
}
df$Test <- paste0(df$Test,'.In',df$Location)
...