заполнить неполную корреляционную матрицу в длинном формате с помощью R - PullRequest
0 голосов
/ 31 мая 2018

У меня есть неполная квадратная матрица в длинном формате, которую я хотел бы заполнить для использования с ggplot2 :: geom_raster.Давайте представим, что это корреляционная матрица со значениями (z) в диапазоне, здесь, от 0 до 1.

df <- data.frame(x=LETTERS[1:3], y=LETTERS[c(3,1,2)], z=c(0,1,-1))
df

Вывод

  x y  z
1 A C  0
2 B A  1
3 C B -1

Я могу завершить это:

library(tidyr)
complete(df,x , y, fill=list(z=NA))
# A tibble: 9 x 3
       x      y     z
  <fctr> <fctr> <dbl>
1      A      A    NA
2      A      B    NA
3      A      C     0
4      B      A     1
5      B      B    NA
6      B      C    NA
7      C      A    NA
8      C      B    -1
9      C      C    NA

Теперь, поскольку предполагается, что это корреляционная матрица, я хотел бы заполнить ее так, чтобы, если я знаю cor (D, A), то в итоге я получил бы cor (A, D) ==кор (D, A).Таким образом, ожидаемый результат будет таким:

# A tibble: 9 x 3
       x      y     z
  <fctr> <fctr> <dbl>
1      A      A    NA
2      A      B    1
3      A      C     0
4      B      A     1
5      B      B    NA
6      B      C    -1
7      C      A    0
8      C      B    -1
9      C      C    NA

Я могу делать сложные вещи, но, возможно, есть простое решение ...

Спасибо

Ответы [ 2 ]

0 голосов
/ 31 мая 2018

У меня есть решение для data.table, использующее другую технику.

library(data.table)
df2 <- complete(df,x , y, fill=list(z=NA))
df2 <- setDT(df2)

df2[!is.na(z),.(x = y, y = x, z = z)][df2,  on = .(x,y)][is.na(z),z:=i.z][,i.z := NULL][]

   x y  z
1: A A NA
2: A B  1
3: A C  0
4: B A  1
5: B B NA
6: B C -1
7: C A  0
8: C B -1
9: C C NA

что он делает: он объединяет df2 с

df2[!is.na(z),.(x = y, y = x, z = z)]
   x y  z
1: C A  0
2: A B  1
3: B C -1

, который является значением некорреляции, но с переключенными x и y.В результате получается

   x y  z i.z
1: A A NA  NA
2: A B  1  NA
3: A C NA   0
4: B A NA   1
5: B B NA  NA
6: B C -1  NA
7: C A  0  NA
8: C B NA  -1
9: C C NA  NA

. Затем я заполняю z значениями iz и подавляю столбец iz.Другой синтаксис, использующий merge:

merge(df2[!is.na(z),.(x = y, y = x, z = z)],df2,all.y = T,by = c("x","y"))[,z:=ifelse(is.na(z.x),z.y,z.x)][,c("z.x","z.y"):=NULL][]

та же идея с dplyr :

library(dplyr)

right_join(df2 %>%
  filter(!is.na(z)) %>%
  rename(x = y, y = x),
  df2, by = c("x","y")) %>%
  mutate(z = ifelse(is.na(z.x),z.y,z.x)) %>%
  select(y,x,z)

  y x  z
1 A A NA
2 B A  1
3 C A  0
4 A B  1
5 B B NA
6 C B -1
7 A C  0
8 B C -1
9 C C NA
0 голосов
/ 31 мая 2018

Решение с использованием tidyverse.Обратите внимание, что перед операцией я изменил все столбцы фактора на символ.df2 - это конечный результат.

library(tidyverse)

df2 <- df %>%
  complete(x, y) %>%
  mutate(Group = map2_chr(x, y, ~paste0(sort(c(.x, .y)), collapse = "_"))) %>%
  group_by(Group) %>%
  mutate(z = mean(z, na.rm = TRUE)) %>%
  ungroup() %>%
  select(-Group)
df2
# # A tibble: 9 x 3
#   x     y         z
#   <chr> <chr> <dbl>
# 1 A     A       NaN
# 2 A     B         1
# 3 A     C         0
# 4 B     A         1
# 5 B     B       NaN
# 6 B     C        -1
# 7 C     A         0
# 8 C     B        -1
# 9 C     C       NaN

ДАННЫЕ

df <- data.frame(x=LETTERS[1:3], y=LETTERS[c(3,1,2)], z=c(0,1,-1),
                 stringsAsFactors = FALSE)
...