Как получить data.frame с прецедентами из таблицы непредвиденных обстоятельств в r?

Я хотел бы воспроизвести некоторые расчеты из книги (логит-регрессия). Книга дает таблицу непредвиденных обстоятельств и результаты.

Вот таблица:

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

    .


    example <- matrix(c(21,22,6,51), nrow = 2, byrow = TRUE)
    #Labels:
    rownames(example) <- c("Present","Absent")
    colnames(example) <- c(">= 55", "<55")

Это дает мне это:

            >= 55 <55
    Present    21  22
    Absent      6  51

Но для использования функции glm() данные должны быть в следующем виде:

(два столбца, один с «Возрастом» и один с «Настоящим», заполненные 0/1)

    age <- c(rep(c(0),27), rep(c(1),73))
    present <- c(rep(c(0),21), rep(c(1),6), rep(c(0),22), rep(c(1),51))

    data <- data.frame(present, age)

    > data
        present age
    1         0   0
    2         0   0
    3         0   0
    .         .   .
    .         .   .
    .         .   .
    100       1   1

Есть ли простой способ получить эту структуру из таблицы/матрицы?


person Martin    schedule 08.04.2016    source источник
comment
Кодирование вручную кажется самым простым способом для одноразового использования. Если вы думаете, что будете делать это много раз, вы можете создать функцию, которая принимает элементы матрицы/таблицы в качестве аргументов для rep() функций, которые у вас есть выше. Это было бы особенно легко, если бы размеры матрицы остались такими же, как 2X2. Если они изменятся, то потребуется больше кодирования.   -  person lmo    schedule 08.04.2016
comment
Ваша переменная возраста, определенная в age <- c(rep(c(0),27), rep(c(1),73)), не соответствует определению таблицы. 27 субъектов в возрасте старше 55 лет должны быть закодированы с помощью 1, а 73 субъекта в возрасте до 55 лет должны быть закодированы с помощью 0.   -  person Paul Rougieux    schedule 08.04.2016
comment
Благодарю вас! Я этого не заметил.   -  person Martin    schedule 08.04.2016


Ответы (5)


reshape2::melt(example)

Это даст вам,

     Var1  Var2 value
1 Present >= 55    21
2  Absent >= 55     6
3 Present   <55    22
4  Absent   <55    51

который вы можете легко использовать для glm

person TheRimalaya    schedule 08.04.2016
comment
Вы также можете получить это с помощью as.data.frame(as.table(example)) (но столбец value равен Freq) - person jaimedash; 08.04.2016
comment
Кроме того, я могу ошибаться, но не уверен, что его можно легко использовать в glm. Я написал ответ, который показывает, как stackoverflow.com/a/36508547/4598520 - person jaimedash; 08.04.2016

Возможно, вы могли бы использовать функцию countsToCases, как определено здесь.

countsToCases(as.data.frame(as.table(example))) 
#        Var1  Var2
#1    Present >= 55
#1.1  Present >= 55
#1.2  Present >= 55
#1.3  Present >= 55
#1.4  Present >= 55
#1.5  Present >= 55
# ...

Вы всегда можете перекодировать переменные в числовые, если хотите.

person mtoto    schedule 08.04.2016

Я бы пошел на:

library(data.table)
tab <- data.table(AGED = c(1, 1, 0, 0),
                  CHD = c(1, 0, 1, 0),
                  Count = c(21, 6, 22, 51))

tabExp <- tab[rep(1:.N, Count), .(AGED, CHD)]

Изменить: краткое объяснение, так как мне потребовалось некоторое время, чтобы понять это:

В объектах data.table .N хранится количество строк группы (если сгруппировано с by) или просто количество строк всего data.table, поэтому в этом примере:

tab[rep(1:.N, Count)]

а также

tab[rep(1:4, Count)]

и наконец

tab[rep(1:4, c(21, 6, 22, 51)]

эквивалентны.

То же самое с базой R:

tab2 <- data.frame(AGED = c(1, 1, 0, 0),
                   CHD = c(1, 0, 1, 0),
                   Count = c(21, 6, 22, 51))

tabExp2 <- tab2[rep(1:nrow(tab2), tab2$Count), c("AGED", "CHD")]
person m-dz    schedule 08.04.2016

Код ниже может показаться длинным, но только инструкции group_by() и do() имеют дело с расширением данных. Все остальное связано с изменением данных в длинном формате и кодированием символьных переменных как 0 и 1. Я попытался начать с точной матрицы, которую вы указали в своем вопросе.

Загрузить пакеты для обработки данных

library(tidyr)
library(dplyr)

Создать фрейм данных

Создайте матрицу, как в вашем примере, но избегайте знаков «>» в ​​именах столбцов.

example <- matrix(c(21,22,6,51), nrow = 2, byrow = TRUE)
rownames(example) <- c("Present","Absent")
colnames(example) <- c("above55", "below55")

Преобразование матрицы во фрейм данных

example <- data.frame(example) %>%
    add_rownames("chd")    

Или просто создайте фрейм данных напрямую

data.frame(chd = c("Present", "Absent"),
           above55 = c(21,6),
           below55 = c(22,51))

Изменить форму данных

data2 <- example %>% 
    gather(age, nrow, -chd) %>%
    # Encode chd and age as 0 or 1
    mutate(chd = ifelse(chd=="Present",1,0),
           age = ifelse(age=="above55",1,0)) %>%
    group_by(chd, age) %>%
    # Expand each variable by nrow
    do(data.frame(chd = rep(.$chd,.$nrow),
                  age = rep(.$age,.$nrow)))

head(data2)
# Source: local data frame [6 x 2]
# Groups: chd, age [1]
# 
#     chd   age
#   (dbl) (dbl)
# 1     0     0
# 2     0     0
# 3     0     0
# 4     0     0
# 5     0     0
# 6     0     0
tail(data2)
# Source: local data frame [6 x 2]
# Groups: chd, age [1]
# 
#     chd   age
#   (dbl) (dbl)
# 1     1     1
# 2     1     1
# 3     1     1
# 4     1     1
# 5     1     1
# 6     1     1

table(data2)
#        age
# chd  0  1
#   0 51  6
#   1 22 21

То же, что и ваш пример, за исключением проблемы кодирования возраста, упомянутой в моем комментарии выше.

person Paul Rougieux    schedule 08.04.2016

Итак, glm не такой уж негибкий. В части ?glm читаем

 For ‘binomial’ and ‘quasibinomial’ families the response can also
 be specified as a ‘factor’ (when the first level denotes failure
 and all others success) or as a two-column matrix with the columns
 giving the numbers of successes and failures.

Я предполагаю, что вы хотите проверить влияние возраста на Present/Absent. Ключ предназначен для указания ответа, например (в псевдокоде) c(success, failure).

Итак, вам нужны такие данные, как data.frame(Age= ..., Present = ..., Absent). Самый простой способ сделать это из вашего example — транспонировать, затем принудить к data.frame и добавить столбец:

example_t <- as.data.frame(t(example))
example_df <- data.frame(example_t, Age=factor(row.names(example_t)))

что дает вам

      Present Absent   Age
>= 55      21      6 >= 55
<55        22     51   <55

Затем вы можете запустить glm:

glm(cbind(Present, Absent) ~ Age, example_df, family = 'binomial')

получить

Call:  glm(formula = cbind(Present, Absent) ~ Age, family = "binomial",
    data = example_for_glm)

Coefficients:
(Intercept)       Age<55
      1.253       -2.094

Degrees of Freedom: 1 Total (i.e. Null);  0 Residual
Null Deviance:      18.7
Residual Deviance: -1.332e-15   AIC: 11.99

Дополнение

Вы также можете попасть сюда через ответ @therimalaya. Но это только первый шаг

as.data.frame(as.table(example))

(только часть пути)

    Var1  Var2 Freq
1 Present >= 55   21
2  Absent >= 55    6
3 Present   <55   22
4  Absent   <55   51

но чтобы на самом деле иметь столбец успехов и неудач, вам нужно сделать что-то еще. Вы можете использовать tidyr, чтобы добраться туда

as.data.frame(as.table(example)) %>% tidyr::spread(Var1, Freq)

похож на мой example_df выше

  Var2 Present Absent
1 >= 55      21      6
2   <55      22     51
person jaimedash    schedule 08.04.2016