Тестирование разницы между пропорциями в R

Я немного запутался с проведением теста пропорций в R. Может быть, это супер очевидно, но prop.test ведет себя не так, как я ожидал, и я хотел бы знать, почему и что использовать вместо этого. Приложение находится в наборе данных о протестных событиях.

Я построил следующий набор данных:

введите здесь описание изображения

где имя относится к типу вычисляемого процента событий. Первая строка относится к мероприятиям, организованным после выборов (aft_elect_prt). В каждой из этих категорий я подсчитываю количество событий, которые (past_pm1) или не были связаны с группой бывшего премьер-министра (past_pm0). Всего относится к количеству событий в наборе данных определенного типа. Доля 0 — это past_pm0/всего, доля 1 — это past_pm1/всего.

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

Читая документацию prop.test, я установил ее как:

prop.test(x = as.numeric(subseted$past_pm1),
          n = subseted$total,
          p = subseted$share0,
          alternative = "two.sided",
          conf.level = 0.95)

Однако это, очевидно, не проверяет то, что я хочу. Это также приводит только к одному значению p, тогда как я хотел бы извлечь значение p для каждой строки. Какую функцию/тест следует использовать вместо этого?

Это код вывода для набора данных:

structure(list(names = c("aft_elect_prt", "ANSM", "bef_elect_prt", 
"big_event", "conf_viol", "coorg", "demo_petition", "economic", 
"NSM", "political"), past_pm0 = c(49.66101, 78.54659, 65.57226, 
49.67205, 39.641924, 69.52704, 286.8565, 68.53114, 100.00488, 
117.97347), past_pm1 = c(33.796, 14.30855, 34.40608, 31.14065, 
9.017051, 30.64896, 120.4515, 20.86095, 19.00836, 71.24065), 
    total = c(83.4570157825947, 92.8551414906979, 99.9783371835947, 
    80.8127028793097, 48.6589741557837, 100.176002234221, 407.307988807559, 
    89.3920872062445, 119.013234868646, 189.21411934495), share0 = c(0.595048954654295, 
    0.8459045857775, 0.655864678761227, 0.614656461548911, 0.814688856223823, 
    0.69404885850245, 0.704274180429913, 0.766635416419863, 0.84028368870382, 
    0.623491895892433), share1 = c(0.404950976057405, 0.154095398168484, 
    0.344135349408928, 0.385343502821669, 0.185311161125829, 
    0.305951119194593, 0.295725847049147, 0.233364614832964, 
    0.159716354412006, 0.376508107569518)), row.names = c(NA, 
-10L), class = "data.frame")

Буду благодарен за любые подсказки!


person eborbath    schedule 23.05.2019    source источник
comment
Я вижу, что числа на изображении имеют разделители тысяч, а данные, которые вы прочитали, отличаются в один миллион раз. Это может привести к проблемам. Способы решения этой проблемы см. здесь: stackoverflow.com/questions/1523126/   -  person AkselA    schedule 23.05.2019
comment
И с этой поправкой все эти пропорции тривиально значимы. Я имею в виду очень, очень, очень значительный. Рассмотрим, скажем, разделение 8000/9000, уже p≈0. prop.test(cbind(8000, 9000))   -  person AkselA    schedule 23.05.2019
comment
@AskelA поднимает важный вопрос. Возможно, более уместным будет вопрос, есть ли значительные отклонения в значении share0? Это требует принятия распределения для этих значений. При нормальном распределении простой тест, чтобы узнать, отличаются ли какие-либо значения от среднего, может быть with(subseted, t.test(share0, mu = mean(share0))). (Этот ответ - нет, p = 0,78)   -  person David O    schedule 23.05.2019
comment
@DavidO делает очень хорошее замечание - я не стал вдаваться в подробности в своем ответе, потому что его часть функционального программирования все еще полезна для решения. Вы можете изменить нулевую гипотезу для каждого отдельного теста пропорций с помощью аргумента p в prop.test(). По умолчанию это 0,5.   -  person qdread    schedule 23.05.2019
comment
Я также только что заметил, что этот вопрос, вероятно, является дубликатом stackoverflow.com/questions/49222353/   -  person qdread    schedule 23.05.2019


Ответы (2)


Функция prop.test не векторизована. Он проводит однократное испытание. Вам нужно явно сопоставить функцию с каждой строкой вашего фрейма данных. Для этого вы можете использовать базовые функции R или функции tidyverse. Вот как вы могли бы сделать это в tidyverse, используя purrr::pmap для применения функции к каждой строке фрейма данных.

library(purrr)
prop_test_list <- pmap(subseted, function(past_pm1, total, ...) prop.test(x = past_pm1, n = total, alternative = 'two.sided', conf.level = 0.95))

Это вернет список тестовых объектов с таким количеством элементов, сколько у вас есть строк в вашем фрейме данных.

Чтобы извлечь вывод из списка в форме фрейма данных, вы можете использовать purrr::map_dfr. Вот пример с несколькими сводными статистическими данными:

map_dfr(prop_tests, ~ data.frame(p = .x$p.value, estimate = .x$estimate, confint_min = .x$conf.int[1], confint_max = .x$conf.int[2]))

вывод:

   p            estimate   confint_min confint_max
1  1.037002e-01 0.4049510  0.30058839   0.5181435
2  5.288024e-11 0.1540954  0.09038891   0.2472255
3  2.553365e-03 0.3441353  0.25382739   0.4465844
4  5.115352e-02 0.3853435  0.28114139   0.5005436
5  2.167205e-05 0.1853112  0.09330970   0.3274424
6  1.540307e-04 0.3059511  0.21985913   0.4071514
7  2.490965e-16 0.2957258  0.25231710   0.3430569
8  7.967215e-07 0.2333646  0.15312169   0.3369412
9  2.252910e-13 0.1597164  0.10130585   0.2407265
10 8.851678e-04 0.3765081  0.30807997   0.4500369
person qdread    schedule 23.05.2019

Базовая функция Vectorize может векторизовать функцию, которая не принимает векторы. Обратите внимание на аргумент SIMPLIFY. При значении по умолчанию TRUE результат упрощается до вектора, массива или матрицы, если это возможно. Здесь имеет смысл сохранить его в виде списка.

vprop.test <- Vectorize(prop.test, SIMPLIFY = FALSE)
ans <- with(subseted, vprop.test(x = past_pm1, n = total))

Чтобы извлечь только p-значения (все они равны 0, как указано в комментариях) и прикрепить их к исходному фрейму данных:

subseted$p.value <- sapply(ans, "[[", "p.value")
person David O    schedule 23.05.2019