我有一个相关数据框架,看起来像这样(尽管我的真实数据中有〜15,000行)
phen1<-c("A","B","C")
phen2<-c("B","C","A")
cors<-c(0.3,0.7,0.8)
data<-as.data.frame(cbind(phen1, phen2, cors))
phen1 phen2 cors
1 A B 0.3
2 B C 0.7
3 C A 0.8
这是在外部创建的,并读入R,我想将此数据帧转换为以phen1和2作为该矩阵的行和列的标签的相关矩阵。我只为下三角或上三角计算了这个,而对于“诊断”则没有1。因此,我希望最终结果是一个完整的相关矩阵,但第一步可能是创建下/上三角形,然后转换为我认为的完整矩阵。我不确定该怎么做。
此外,结果可能不是按照直观的顺序排列,但是我不确定这是否重要,但是理想情况下,我想使用phen1和phen 2中的标签来确保矩阵具有如果可以的话,将正确的值放在正确的位置?
本质上来说,我想要这样的最终结果:
A B C
A 1 0.3 0.8
B 0.3 1 0.7
C 0.8 0.7 1
答案 0 :(得分:2)
我认为必须有一种优雅的方法,但是,有一种dplyr
和tidyr
的可能性:
data %>%
spread(phen1, cors) %>%
rename(phen = "phen2") %>%
bind_rows(data %>%
spread(phen2, cors) %>%
rename(phen = "phen1")) %>%
group_by(phen) %>%
summarise_all(~ ifelse(all(is.na(.)), 1, first(na.omit(.))))
phen A B C
<chr> <dbl> <dbl> <dbl>
1 A 1 0.3 0.8
2 B 0.3 1 0.7
3 C 0.8 0.7 1
答案 1 :(得分:2)
您可以为此使用Matrix包。您所拥有的只是数据的稀疏表示,并且您想要将其转换为密集(冗余)矩阵。
data <- data.frame(phen1, phen2, cors)
inds <- cbind(as.integer(data$phen1), as.integer(data$phen2))
inds <- t(apply(inds, 1, sort))
library(Matrix)
res <- sparseMatrix(i = inds[,1],
j = inds[,2],
x = data$cors,
symmetric = TRUE)
#3 x 3 sparse Matrix of class "dsCMatrix"
#
#[1,] . 0.3 0.8
#[2,] 0.3 . 0.7
#[3,] 0.8 0.7 .
res <- as.matrix(res)
diag(res) <- 1
dimnames(res) <- list(sort(data$phen1), sort(data$phen2))
res
# A B C
#A 1.0 0.3 0.8
#B 0.3 1.0 0.7
#C 0.8 0.7 1.0
答案 2 :(得分:2)
这是基数R中的另一个,我们在其中创建与data
相同的对称数据帧,但将phen1
和phen2
的列取反。然后,我们使用xtabs
来获取相关矩阵并将对角线设置为1。
data1 <- data.frame(phen1 = data$phen2, phen2 = data$phen1, cors = data$cors)
df <- rbind(data, data1)
df1 <- as.data.frame.matrix(xtabs(cors ~ ., df))
diag(df1) <- 1
df1
# A B C
#A 1.0 0.3 0.8
#B 0.3 1.0 0.7
#C 0.8 0.7 1.0
数据
phen1<-c("A","B","C")
phen2<-c("B","C","A")
cors<-c(0.3,0.7,0.8)
data<- data.frame(phen1, phen2, cors)
答案 3 :(得分:1)
这是另一个选择。
首先将数据的形状从长到宽调整为matrix
。您可以选择不同的方法(reshape2
,tidyr
等);这里我使用tidyr::spread
。
library(tidyverse)
mat <- data %>% spread(phen2, cors) %>% column_to_rownames("phen1") %>% as.matrix()
然后我们分别从上三角矩阵和下三角矩阵中填充缺失的NA
值,并用1
填充对角线。
mat[lower.tri(mat)] <- mapply(sum, mat[lower.tri(mat)], mat[upper.tri(mat)], na.rm = T)
mat[upper.tri(mat)] <- mat[lower.tri(mat)]
diag(mat) <- 1
mat
# A B C
#A 1.0 0.3 0.8
#B 0.3 1.0 0.7
#C 0.8 0.7 1.0
答案 4 :(得分:0)
您可以使用重塑库。
library(reshape)
data <- melt(data)
your_mat <- cast(data, phen1 ~ phen2 )
输出:
phen1 A B C
1 A <NA> 0.3 <NA>
2 B <NA> <NA> 0.7
3 C 0.8 <NA> <NA>
之所以会输入NA,是因为您的输入表中缺少许多组合。为了避免这种情况,您需要一个像这样的输入表:
phen1 phen2 cors
1 A B 0.3
2 B C 0.7
3 C A 0.8
4 A C 0.8
5 B A 0.3
6 C B 0.7
7 A A 1.0
8 B B 1.0
9 C C 1.0
答案 5 :(得分:0)
已经有很多解决方案,但是我将以另一种方式提出。注意:我正在设置数据,以使cors
是数字而不是原始数据框中的一个因数。
data <- data.frame(phen1, phen2, cors)
然后,我们可以使用缺少的组合来扩展数据框,然后使用reshape2::acast()
将数据转换为宽格式。
library(tidyverse)
library(reshape2)
data %>%
select(phen1 = phen2, phen2 = phen1, cors) %>%
bind_rows(data) %>%
acast(phen1 ~ phen2, fill = 1)
acast
方便您使用其他指定值(在本例中为1)填充缺失值。
另外,请检出corrr
软件包,它可能可以更整洁地完成此操作。
答案 6 :(得分:0)
这是我写的一个函数:
long2cormat <- function(xlong, x = "x", y = "y", r = "r") {
# Takes some inspiration from https://stackoverflow.com/a/57904948/180892
xlong <- xlong[,c(x, y, r)]
names(xlong) <- c("x", "y", "r")
data1 <- data.frame(x = xlong$x, y = xlong$y, r = xlong$r)
data2 <- data.frame(x = xlong$y, y = xlong$x, r = xlong$r)
df <- rbind(data1, data2)
uv <- unique(c(df$x, df$y))
df1 <- matrix(NA, nrow = length(uv), ncol = length(uv), dimnames = list(uv, uv))
for (i in seq(nrow(df))) df1[df$x[i], df$y[i]] <- df$r[i]
diag(df1) <- 1
df1
}
要运行它,请执行以下操作:
xlong <- data.frame(phen1 = c("A","B","C"),
phen2 = c("B","C","A"),
cors = c(0.3,0.7,0.8))
long2cormat(xlong, "phen1", "phen2", "cors")
重要的是,对于我自己的用例,它将缺失的相关性保留为 NA。