Использовать групповое среднее значение для проведения одного теста в нескольких группах - PullRequest
0 голосов
/ 21 января 2020

Меня интересует, как могут отличаться результаты при сравнении средних значений с использованием t-критерия с двумя выборками, а не t-критерия с одним образцом из тех же данных. Сравниваются две оценки, в которых «подсчеты» выбираются случайным образом из разных групп населения («Group_ID») с использованием двух разных методов («источник»). Результат р> 0,05 указывает на то, что средние значения статистически не различаются (т.е. оба метода оценки дают схожие результаты). Исходные данные для источника = A надежны и всегда доступны. Необработанные данные для источника = B могут быть недоступны, но среднее значение всегда будет предоставлено. Используя набор тестовых данных, я хочу изучить, как отличаются результаты t.test, используя один образец t.test в отличие от двух образцов t.test.

Используя функции dplyr и broom, я определил, как сделать несколько t-тестов с двумя образцами в нескольких случаях («Group_ID»), где были проведены две оценки. Данные из двух источников объединяются для создания фрейма данных из трех столбцов, содержащего необработанные значения («количество»), идентифицированные одним из двух источников («источник»).

glimpse(Data)

Observations: 2,552
Variables: 3
$ Group_ID    <fct> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1...
$ count       <dbl> 7, 8, 5, 5, 7, 3, 4, 2, 8, 11, 12, 1, 3, 5, 5, 12, 1, 5...
$ source      <chr> "B", "B", "B", "B", "B", "B", "B", "B",...

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

Data_Stats <- Data %>% 
    group_by(Group_ID) %>%
    do(tidy(t.test(count ~ source, alt="two.sided", conf=0.95, var.eq=FALSE, paired=FALSE, data = .)))

Результаты в

Observations: 38
Variables: 11
Groups: Group_ID [38]
$ Group_ID <fct> 1, 1029, 1032, 1033, 1041, 1044, 1064, 1065, 1067, 1080, 1081, 1083, 1084, 117, 127, 180, 2...
$ estimate    <dbl> -0.4250000, -6.5000000, -1.1944444, 0.3437500, -5.2250000, -1.4375000, -1.6250000, -1.48387...
$ estimate1   <dbl> 5.250000, 9.166667, 5.833333, 6.156250, 5.375000, 3.937500, 2.075000, 6.000000, 4.108108, 9...
$ estimate2   <dbl> 5.675000, 15.666667, 7.027778, 5.812500, 10.600000, 5.375000, 3.700000, 7.483871, 6.540541,...
$ statistic   <dbl> -0.42469044, -3.42643903, -1.19922603, 0.32509809, -3.36599817, -1.94947775, -2.47005992, -...
$ p.value     <dbl> 6.723526e-01, 1.480949e-03, 2.355386e-01, 7.463614e-01, 1.509467e-03, 5.649284e-02, 1.57612...
$ parameter   <dbl> 70.66653, 38.05593, 55.46167, 54.07284, 47.94418, 53.45682, 75.67387, 44.38453, 49.87894, 6...
$ conf.low    <dbl> -2.420560, -10.340117, -3.190125, -1.776090, -8.346179, -2.916196, -2.935370, -3.969856, -5...
$ conf.high   <dbl> 1.570559944, -2.659882919, 0.801236360, 2.463590202, -2.103821060, 0.041195928, -0.31462953...
$ method      <chr> "Welch Two Sample t-test", "Welch Two Sample t-test", "Welch Two Sample t-test", "Welch Two...
$ alternative <chr> "two.sided", "two.sided", "two.sided", "two.sided", "two.sided", "two.sided", "two.sided", ...

Я знаю, что могу получить средства для каждого случая, используя:

Data_means <- Data %>% 
    group_by(Group_ID) %>% 
    summarize(count_mean = mean(count))

Я ищу предложение о том, как наилучшим образом использовать среднее значение для каждого Group_ID из source = 2 в качестве значения для "mu =" "вызвать функцию t.test для сравнения со средним значением source = 1, используя t-тест для одной выборки для каждого из 38 различных идентификаторов Group_ID?

1 Ответ

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

Это проблема, которая не очень хорошо подходит для обработки данных с помощью dplyr, и, вероятно, проще создавать тесты, используя split.data.frame и lapply, но вот как вы могли бы go об этом без сращивания различные кадры данных вместе.

Во-первых, мне нужны воспроизводимые данные в тех же строках, что и данные в вашем вопросе:

library(tidyverse)

set.seed(69)
df <- data.frame(Group_ID = factor(rep(1:4, each = 40)),
                 count = sample(10, 160, T) + rep(1:2, 80) + rep(1:4, each = 40),
                 source = factor(rep(c("A", "B"), 80)))

Теперь мы можем получить значения p для двух выборок в виде похож на способ, который вы использовали. Затем мы используем прием средних значений для каждого источника внутри каждого идентификатора, затем разгруппируем фрейм данных и дублируем средние значения, но смещая их так, чтобы средние значения «B» находились в строках «A». После этого мы можем использовать это в качестве среднего значения для t-критерия с одной выборкой для «A». Когда мы подводим итоги, у нас есть данные как для 1, так и для 2 выборок.

df                                                                      %>%
group_by(Group_ID)                                                      %>%
mutate(two_group_pval = t.test(count ~ source)$p.value)                 %>%
group_by(Group_ID, source)                                              %>%
mutate(mean_A = mean(count))                                            %>%
arrange(source, .by_group = T)                                          %>%
group_by(Group_ID)                                                      %>%
mutate(mean_B = lead(mean_A, length(which(source == "B"))))             %>%
filter(source == "A")                                                   %>%
group_by(Group_ID)                                                      %>%
mutate(one_group = t.test(count, mu = mean(mean_B, na.rm = T))$p.value) %>%
summarise(observations = length(count),
          mean_A = mean(mean_A, na.rm = T),
          mean_B = mean(mean_B, na.rm = T),
          one_sample_p_value = mean(one_group),
          two_sample_p_value = mean(two_group_pval))

#> # A tibble: 4 x 6
#>   Group_ID observations mean_A mean_B one_sample_p_value two_sample_p_value
#>   <fct>           <int>  <dbl>  <dbl>              <dbl>              <dbl>
#> 1 1                  20    6.6   8.65            0.00341             0.0201
#> 2 2                  20    8.3   9.85            0.0364              0.0999
#> 3 3                  20    9.9  11.5             0.0103              0.0600
#> 4 4                  20   10.4  11.4             0.122               0.290 

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


РЕДАКТИРОВАТЬ

Исходя из требований ОП, которые были уточнены, приведенный выше код не будет работать для данного примера двух уровней для Group_ID. Вот как вы могли бы решить проблему в базе R для произвольных уровней, используя не требующий пояснений код:

multi_ss_t_test <- function(x, y) as.numeric(t.test(x$count, mu = y)$p.value)
multi_ts_t_test <- function(x, y) as.numeric(t.test(x$count, y$count)$p.value)

source_dfs <- split.data.frame(df, df$source)

A_groups   <- split.data.frame(source_dfs$A, source_dfs$A$Group_ID)
B_groups   <- split.data.frame(source_dfs$B, source_dfs$B$Group_ID)

B_means    <- tapply(source_dfs$B$count, source_dfs$B$Group_ID, mean)
A_means    <- tapply(source_dfs$A$count, source_dfs$A$Group_ID, mean)

ss_pvals   <- mapply(multi_ss_t_test, A_groups, B_means)
ts_pvals   <- mapply(multi_ts_t_test, A_groups, B_groups)

result     <- data.frame(group = levels(df$Group_ID),
                         source_A_mean = A_means,
                         source_B_means = B_means,
                         one_sample_pval = ss_pvals,
                         two_sample_pval = ts_pvals)

Теперь, если я предоставлю фрейм данных с 38 уровнями, вы увидите, что он выведет оба образца и значения p для двух выборок для каждого Group_ID:

set.seed(69)
df <- data.frame(Group_ID = factor(rep(rep(1:38, each = 20), 2)),
                 count = c(sample(10:40, 760, T), sample(12:42, 760, T)),
                 source = rep(c("A", "B"), each = 760))

Запустите через вышеуказанную программу, это даст:

as_tibble(result)
#> # A tibble: 38 x 5
#>    group source_A_mean source_B_means one_sample_pval two_sample_pval
#>    <fct>         <dbl>          <dbl>           <dbl>           <dbl>
#>  1 1              24.5           25.6          0.620           0.724 
#>  2 2              23.6           25.0          0.407           0.608 
#>  3 3              24.2           29.7          0.0154          0.0438
#>  4 4              26             22.6          0.123           0.264 
#>  5 5              26.6           25.6          0.531           0.683 
#>  6 6              26.8           24.7          0.303           0.414 
#>  7 7              25.5           26            0.807           0.852 
#>  8 8              24.3           28.9          0.0167          0.0887
#>  9 9              23.6           26.6          0.137           0.255 
#> 10 10             25.8           27.1          0.533           0.651 
#>#... with 28 more rows

Более эффективный подход, если вы просто хотите значения p будет:

get_pvals <- function(x)
{
  c(one_sample_p_value = t.test(x$count ~ x$source)$p.value,
    two_sample_p_value = t.test(x$count[x$source == "A"], 
                                mu = mean(x$count[x$source == "B"]))$p.value) 
}

split(df, list(group = df$Group_ID)) %>% sapply(get_pvals) %>% t %>% as.data.frame()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...