用逻辑值熔化矩阵

melting matrices with logical values

我有一个带有成对比较的矩阵,其中的上三角和对角线设置为 NA

df <- data.frame(a=c(NA,1,2), b=c(NA,NA,3), c=c(NA,NA,NA))
row.names(df) <- names(df)

,然后是 na.omit,所以我想要的输出是:

Var1 Var2 Value
a     b   1
a     c   2
b     c   3

然而,df$c 全部为 NA,因此合乎逻辑,将被 melt 用作非测量变量。 因此 melt(df) 的输出不是我要找的。

library(reshape2)
melt(df)

如何防止 melt 使用 df$c 作为 id 变量?

诀窍是将行名转换为列名,然后再转换为长格式。 tidyverse 中的一种方法是,

library(tidyverse)

df %>% 
  rownames_to_column() %>% 
  gather(var, val, -1) %>% 
  filter(!is.na(val))


#  rowname var val
#1       b   a   1
#2       c   a   2
#3       c   b   3

正如@Humpelstielzche 在评论中提到的那样,在 gather 中有一个 na.rm 参数,因此我们可以省略最后一个过滤,即

df %>% 
 rownames_to_column() %>% 
 gather(var, val, -1, na.rm = TRUE)

在base R中,我们可以使用rowcol分别获取行名和列名,然后过滤NA值。

df1 <- data.frame(col = colnames(df)[col(df)], row = rownames(df)[row(df)], 
                  value = unlist(df), row.names = NULL)

df1[!is.na(df1$value), ]

#  col row value
#2   a   b     1
#3   a   c     2
#6   b   c     3

虽然您已经有了其他答案,但如果调用了适当的函数,则 可以 通过 reshape2melt 来实现。在这种情况下,您不希望应用 reshape2:::melt.data.frame,而是应用 reshape2:::melt.matrix。所以,试试:

melt(as.matrix(df), na.rm=TRUE)
#  Var1 Var2 value
#2    b    a     1
#3    c    a     2
#6    c    b     3

如果您随后查看 ?reshape2:::melt.data.frame,您将看到语句:

This code is conceptually similar to ‘as.data.frame.table’

这意味着您还可以使用更复杂的方法:

na.omit(as.data.frame.table(as.matrix(df), responseName="value"))
#  Var1 Var2 value
#2    b    a     1
#3    c    a     2
#6    c    b     3