简体   繁体   English

从 r 中的长表创建一个对称矩阵

[英]Create a matrix symmetric from long table in r

This is my data这是我的数据

df <- data.frame (Var1  <- c("a", "b", "c","d","e","b","c","d","e","c","d","e","d","e","e"),
                  Var2 <- c("a","a","a","a","a","b","b","b","b","c","c","c","d","d","e")
                  pre <- c(1,2,3,4,5,1,6,7,8,1,9,10,1,11,1) )

I would like to build a symmetric matrix with Var1 and Var2 function as rownames and colnames, and the matrix values are the Corresponding number in "pre" in r, like this:我想用 Var1 和 Var2 function 作为行名和列名构建一个对称矩阵,矩阵值是 r 中“pre”中的对应数字,如下所示:

  a b c d e 
a 1 2 3 4 5
b 2 1 6 7 8 
c 3 6 1 9 10
d 4 7 9 1 11
e 5 8 10 11 1

This seems to be an easy problem, but I have googled a lot of posts, but it has not been solved, so I come here to ask, thank you!这似乎是一个简单的问题,但是我google了很多帖子,但都没有解决,所以特地来问一下,谢谢!

Mengying梦莹

You can get the data in wide format first.您可以先获取宽格式的数据。

library(dplyr)
library(tidyr)

mat <- df %>%
  pivot_wider(names_from = Var2, values_from = pre, values_fill = 0) %>%
  column_to_rownames('Var1') %>%
  as.matrix()

mat
#  a b  c  d e
#a 1 0  0  0 0
#b 2 1  0  0 0
#c 3 6  1  0 0
#d 4 7  9  1 0
#e 5 8 10 11 1

Since you have a symmetric matrix you can copy the lower triangular matrix to upper triangle.由于您有一个对称矩阵,您可以将下三角矩阵复制到上三角。

mat[upper.tri(mat)] <- t(mat)[upper.tri(mat)]
mat

#  a b  c  d  e
#a 1 2  3  4  5
#b 2 1  6  7  8
#c 3 6  1  9 10
#d 4 7  9  1 11
#e 5 8 10 11  1

data数据

df <- data.frame (Var1  = c("a", "b", "c","d","e","b","c","d","e","c","d","e","d","e","e"),
                  Var2 = c("a","a","a","a","a","b","b","b","b","c","c","c","d","d","e"),
                  pre = c(1,2,3,4,5,1,6,7,8,1,9,10,1,11,1) )

Here is an option with igraph package这是igraph package 的一个选项

g <- graph_from_data_frame(df,directed = FALSE)
E(g)$pre <- df$pre
get.adjacency(g,attr = "pre")

which gives这使

  a b  c  d  e
a 1 2  3  4  5
b 2 1  6  7  8
c 3 6  1  9 10
d 4 7  9  1 11
e 5 8 10 11  1

Base R solution (using data provided by Ronak):基础 R 解决方案(使用 Ronak 提供的数据):

# Crosstab: 
mdat <- as.data.frame.matrix(xtabs(pre ~ Var1 + Var2, df))

# Reflect on the diag (thanks @Ronak Shah):
mdat[upper.tri(mdat)] <- t(mdat)[upper.tri(mdat)]

As @ThomasIsCoding points as well we can use this one-liner:正如@ThomasIsCoding 指出的那样,我们也可以使用这个单线:

xtabs(pre ~ ., unique(rbind(df, cbind(setNames(rev(df[-3]), names(df)[-3]), df[3] ))))

As @thelatemail points out we can also:正如@thelatemail 指出的那样,我们还可以:

xtabs(pre ~ ., unique(data.frame(Map(c, df, df[c(2,1,3)]))))

Here's a base R version:这是一个基本的 R 版本:

df <- data.frame (Var1  = c("a", "b", "c","d","e","b","c","d","e","c","d","e","d","e","e"),
                  Var2 = c("a","a","a","a","a","b","b","b","b","c","c","c","d","d","e"),
                  pre = c(1,2,3,4,5,1,6,7,8,1,9,10,1,11,1))

# Generate new matrix/data frame
mat2 <- matrix(0, length(unique(df$Var1)), length(unique(df$Var2)))

# Name the columns and rows so we can access values
rownames(mat2) <- unique(df$Var1)
colnames(mat2) <- unique(df$Var2)

# Save values into appropriate places into data frame
mat2[as.matrix(df[, 1:2])] <- as.matrix(df[, 3])

# Using upper triangle trick from @Ronak Shah's answer
mat2[upper.tri(mat)] <- t(mat2)[upper.tri(mat2)]

# See results
mat2
#   a b  c  d  e
# a 1 2  3  4  5
# b 2 1  6  7  8
# c 3 6  1  9 10
# d 4 7  9  1 11
# e 5 8 10 11  1

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM