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

У меня есть следующие панельные данные с некоторыми людьми, у которых больше наблюдений, чем у других.

id <- c("John","John","John","John","John",
        "Mike","Mike","Mike","Mike", 
        "Andrea","Andrea","Andrea","Andrea","Andrea","Andrea","Andrea")
time <- c(1:5, 1:4, 1:7)
observation <- c(rnorm(1:5), rnorm(1:4), rnorm(1:7))

paneldata <- data.frame(id, time, observation)

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

Корреляция между Майком и Джоном: следует учитывать только время с 1 по 4.

Корреляция между Джоном и Андреа: только время от 1 до 5 и т. д.

Как лучше всего достичь этих результатов?


person D Pinto    schedule 16.08.2015    source источник


Ответы (1)


Я бы предложил расширить ваш набор данных в широком формате, а затем просто запустить cor по всему набору данных (при удалении time) и указать "pairwise.complete.obs" в функции cor, чтобы он сравнивал только относительные наблюдения. Я бы также посоветовал вам использовать set.seed при создании случайного набора данных. Эти результаты будут соответствовать set.seed(123)

library(dplyr)
library(tidyr)
paneldata %>%
  spread(id, observation) %>%
  select(-time) %>%
  cor(., use = "pairwise.complete.obs")
#            Andrea       John       Mike
# Andrea  1.0000000  0.1288513 -0.3770482
# John    0.1288513  1.0000000 -0.8471950
# Mike   -0.3770482 -0.8471950  1.0000000

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

#      Andrea        John       Mike
# 1 -0.4456620 -0.56047565  1.7150650
# 2  1.2240818 -0.23017749  0.4609162
# 3  0.3598138  1.55870831 -1.2650612
# 4  0.4007715  0.07050839 -0.6868529
# 5  0.1106827  0.12928774         NA
# 6 -0.5558411          NA         NA
# 7  1.7869131          NA         NA

Как указал @akrun в комментариях, вы можете добиться аналогичного результата, используя reshape2::acast, что также сэкономит вам усилия по удалению столбца time, поскольку он преобразует его в имена строк.

library(reshape2)
cor(acast(paneldata, time ~ id, value.var = 'observation'), use = 'pairwise.complete.obs')
#            Andrea       John       Mike
# Andrea  1.0000000  0.1288513 -0.3770482
# John    0.1288513  1.0000000 -0.8471950
# Mike   -0.3770482 -0.8471950  1.0000000
person David Arenburg    schedule 16.08.2015
comment
Я пытался использовать ваш код на большом наборе панельных данных (1,1 миллиона наблюдений), и он очень медленный. Есть ли у вас какие-либо рекомендации, как рассчитать корреляции быстрее? - person Mislav; 19.09.2018