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

У меня есть этот кадр данных в r (ссылка) (примеры строк и столбцы ниже)

FocalID     Mother   Adelaide Asimov Austen Brazzaville Lusaka Kinshasa
Adelaide    HalfEar    0      0.0380 0.0417      0.0366 0.0278   0.0385
Asimov      Lusaka     0.0380 0      0.0845      0.0357 0.169    0.0641
Austen      Kinshasa   0.0417 0.0845 0           0.0526 0.0952   0.0411
Brazzaville NA         0.0366 0.0357 0.0526      0      0.0395   0.0488

Я хотел бы добавить новую переменную df$cor, в которой значение в каждой строке является результатом корреляции. Корреляция должна быть между двумя векторами: (1) столбцом, имя столбца которого соответствует значению переменной df$FocalID в этой строке, и (2) столбцом, имя столбца которого соответствует значению переменной df$Mother в этой строке. .

Если вектор, соответствующий столбцу, совпадающему с именем матери, отсутствует (либо потому, что мать неизвестна (NA в df$Mother), либо отсутствует в colnames), корреляция должна дать NA.

Я пробовал следующий код:

df$cor <- cor(df[, colnames(df) %in% df$FocalID], df[, colnames(df) %in% df$Mother])

Однако результат не кажется правильным. Есть идеи?


person Vittoria Roatti    schedule 27.12.2020    source источник


Ответы (1)


Если нам нужно сделать это для каждого попарного столбца, мы проверяем, не являются ли столбцы «FocalID», «Mother» не-NA с complete.cases. Затем выполните цикл по столбцам, указав подмножество только столбцов, отличных от NA, с помощью apply и MARGIN = 1, проверьте, являются ли эти элементы %in% именами столбцов набора данных, выберите данные, примените cor и создайте новый столбец Cor

i1 <-  complete.cases(df[1:2])
df$Cor <- NA_real_
df$Cor[i1] <-  apply(df[i1, 1:2], 1, function(x) 
   if(all(x %in% names(df))) cor(df[, x[1]], df[, x[2]]) else NA)

-выход

df$Cor
#[1]          NA  0.09769710  0.26956397          NA  0.04820137 -0.07776837          NA  0.19553956 -0.09596063          NA  0.04806345
#[12]  0.66489746          NA          NA          NA -0.04254666 -0.05975570  0.47359966  0.09745244          NA          NA  0.24750130
#[23]          NA          NA          NA          NA          NA          NA          NA          NA  0.10822526          NA  0.07093166
#[34]          NA          NA -0.18088278 -0.17548394  0.11585058  0.07278060  0.36327624  0.10178624          NA          NA          NA
#[45]  0.20491334          NA

Или используя rowwise из dplyr

library(dplyr)
df <- df %>%
        rowwise %>% 
        mutate(Cor = if(!is.na(FocalID) & !is.na(Mother) & 
           all(c(FocalID, Mother) %in% names(.)))
          cor(df[[FocalID]], df[[Mother]]) else NA_real_)

данные

library(readxl)
df <- read_excel(file.choose(), na = "NA")
person akrun    schedule 27.12.2020
comment
Благодарю вас! Замечательно! Я нахожу второе решение (dplyr) лучшим, потому что оно не зависит от знания номеров интересующих столбцов. Можно ли также «изменить» векторы для корреляции, удалив значения, полученные в результате пересечения FocalID с самим собой и FocalID с его Матерью? - person Vittoria Roatti; 28.12.2020
comment
@VittoriaRoatti Вы имели в виду df %>% filter(FocalID != Mother) %>% rowwise %>%.. - person akrun; 28.12.2020
comment
Я не уверена. Я имею в виду, что, чтобы избежать включения людей, чьи сети участвуют в корреляции, извлеченные векторы (например, для второй строки в приведенном выше примере: столбец Asimov для FocalID и столбец Lusaka для матери) должны пропустить значения, которые в кадре данных , получаются в результате взаимодействия идентификаторов векторов друг с другом и сами с собой (они должны иметь на два значения меньше: удаление значений Азимов с Азимов и Азимов с Лусака в векторе Азимов; удаление значений Лусака с Лусака и Лусака с Азимов в вектор Лусака). - person Vittoria Roatti; 28.12.2020
comment
Извините, если что не так :/ - person Vittoria Roatti; 28.12.2020
comment
@VittoriaRoatti В этом случае вам может понадобиться df %>% filter(FocalID != Mother, !duplicated(paste(pmin(FocalID, Mother), pmax(FocalID, Mother)))) - person akrun; 28.12.2020
comment
Благодарю вас! Я попробую сейчас. Его нужно добавить перед %›% построчно %›% ..., верно? - person Vittoria Roatti; 28.12.2020
comment
@VittoriaRoatti Да, filtering предшествует rowwise - person akrun; 28.12.2020