У меня есть два фрейма данных:

a <- structure(list(Bacteria_A = c(12, 23, 45, 32, 34, 0), Bacteria_B = c(23, 
12, 33, 44, 55, 3), Bacteria_C = c(25, 10, 50, 38, 3, 34), Group = structure(c(1L, 
1L, 1L, 1L, 1L, 1L), class = "factor", .Label = "soil")), class = "data.frame", row.names = c("Sample_1", 
"Sample_2", "Sample_3", "Sample_4", "Sample_5", "Sample_6"))

b <- structure(list(Bacteria_A = c(14, 10, 40, 40, 37, 3), Bacteria_B = c(25, 
14, 32, 23, 45, 35), Bacteria_C = c(12, 34, 45, 22, 7, 23), Group = structure(c(1L, 
1L, 1L, 1L, 1L, 1L), class = "factor", .Label = "water")), class = "data.frame", row.names = c("Sample_1", 
"Sample_2", "Sample_3", "Sample_4", "Sample_5", "Sample_6"))

> a
         Bacteria_A Bacteria_B Bacteria_C Group
Sample_1         12         23         25  soil
Sample_2         23         12         10  soil
Sample_3         45         33         50  soil
Sample_4         32         44         38  soil
Sample_5         34         55          3  soil
Sample_6          0          3         34  soil
> b
         Bacteria_A Bacteria_B Bacteria_C Group
Sample_1         14         25         12 water
Sample_2         10         14         34 water
Sample_3         40         32         45 water
Sample_4         40         23         22 water
Sample_5         37         45          7 water
Sample_6          3         35         23 water

Я хочу сравнить разницу между группами по образцам между почвой и водой.

Например, для Bacteria_A я хочу знать, есть ли разница между почвой и водой. То же самое для Bacteria_B и Bacteria_c (у меня есть 900 бактерий). Я хотя бы из t-теста, но не уверен, как это сделать с двумя кадрами данных.

Забыл упомянуть, что не все бактерии присутствуют в обоих данных, поэтому может случиться так, что одна бактерия отсутствует в одной из сред. Если бактерии обнаруживаются в обеих средах, они имеют одно и то же имя.

Исходный кадр данных составляет 160 выборок на 500 бактерий, и данные обычно не распространяются.

Спасибо за вашу помощь.

r
0
david 27 Янв 2020 в 18:03

3 ответа

Лучший ответ

Ваш values не соответствует нормальному или почти нормальному распределению, поэтому вам следует держаться подальше от t-критерия. Если вы не уверены, с каким дистрибутивом вы имеете дело, вы можете использовать wilcox.test.

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

library(tidyr)
library(dplyr)

bind_rows(a,b) %>% 
pivot_longer(c(Bacteria_A, Bacteria_B, Bacteria_C)) %>% 
group_by(name) %>% 
summarise(mean_soil = mean(value[Group == "soil"]), 
          mean_water = mean(value[Group == "water"]), 
          pvalue = wilcox.test(value ~ Group)$p.value)

Что дает вам

#> # A tibble: 3 x 4
#>   name       mean_soil mean_water pvalue
#>   <chr>          <dbl>      <dbl>  <dbl>
#> 1 Bacteria_A      24.3       24    0.936
#> 2 Bacteria_B      28.3       29    0.873
#> 3 Bacteria_C      26.7       23.8  0.748
0
Allan Cameron 27 Янв 2020 в 15:23

Прежде всего, я хочу отметить, что существуют статистические методы для сравнения, которые являются более адекватными, чем критерий Стьюдента. Они учитывают распределение, из которого приходят числа (обычно отрицательно-биномиальные). Вы можете проверить наш пакет DESeq2, например. Что касается вашей технической проблемы, я бы сделал:

for (bac in setdiff(intersect(colnames(a), colnames(b)), "Group")){
  print(t.test(a[,bac], b[,bac]))
}
1
asafpr 27 Янв 2020 в 15:16

Он находит имена бактерий, которые существуют в обоих фреймах данных, а затем выполняет t.test между одними и теми же именами, давая список L, чьи имена являются именами бактерий. Последняя строка использует tidy для преобразования L в кадр данных. Вы можете заменить t.test на wilcox.test, если вы предпочитаете непараметрический тест. (Конечно, это не учитывает проблемы выполнения нескольких тестов гипотезы, а просто делает вычисления).

Name <- intersect(names(Filter(is.numeric, a)), names(Filter(is.numeric, b)))
L <- Map(t.test, a[Name], b[Name])

library(broom)
cbind(Name, do.call("rbind", lapply(L, tidy)))

Последняя строка дает следующий фрейм данных:

                 Name   estimate estimate1 estimate2   statistic   p.value
Bacteria_A Bacteria_A  0.3333333  24.33333  24.00000  0.03485781 0.9728799
Bacteria_B Bacteria_B -0.6666667  28.33333  29.00000 -0.07312724 0.9435532
Bacteria_C Bacteria_C  2.8333333  26.66667  23.83333  0.30754940 0.7650662
           parameter  conf.low conf.high                  method alternative
Bacteria_A  9.988603 -20.97689  21.64356 Welch Two Sample t-test   two.sided
Bacteria_B  7.765869 -21.80026  20.46692 Welch Two Sample t-test   two.sided
Bacteria_C  9.492873 -17.84326  23.50993 Welch Two Sample t-test   two.sided

Заметка

LinesA <- "Bacteria_A Bacteria_B Bacteria_C Group
Sample_1         12         23         25  soil
Sample_2         23         12         10  soil
Sample_3         45         33         50  soil
Sample_4         32         44         38  soil
Sample_5         34         55          3  soil
Sample_6          0          3         34  soil"

LinesB <- "Bacteria_A Bacteria_B Bacteria_C Group
Sample_1         14         25         12 water
Sample_2         10         14         34 water
Sample_3         40         32         45 water
Sample_4         40         23         22 water
Sample_5         37         45          7 water
Sample_6          3         35         23 water"

a <- read.table(text = LinesA, as.is = TRUE)
b <- read.table(text = LinesB, as.is = TRUE)
0
G. Grothendieck 27 Янв 2020 в 15:57