获取稀疏矩阵非零元素的向量,同时保留列和行名称。

3

假设我有以下矩阵:

mat <- matrix(data = c(1, 2, 3, 0, 0, 0, 0, 0, 0, 
                       0, 0, 0, 2, 3, 4, 0, 0, 0,
                       0, 0, 0, 0, 0, 0, 5, 6, 7),
              nrow = 9, 
              dimnames = list(c(paste0("x", 1:3),
                                paste0("y", 1:3),
                                paste0("z", 1:3)),
                              c("a", "b", "c")))


   a b c
x1 1 0 0
x2 2 0 0
x3 3 0 0
y1 0 2 0
y2 0 3 0
y3 0 4 0
z1 0 0 5
z2 0 0 6
z3 0 0 7

我希望得到一个向量,只保留非零元素,而不是矩阵。

red <- apply(mat, 1, function(x) x[x != 0])

x1 x2 x3 y1 y2 y3 z1 z2 z3 
 1  2  3  2  3  4  5  6  7 

有没有办法让减少的向量保留列名?最好是按照“列名+字符+行名”的模式。请参见下面所需的输出。请注意,我们事先不知道会有多少列/行,也不知道它们的名称是什么。
a=x1 a=x2 a=x3 b=y1 b=y2 b=y3 c=z1 c=z2 c=z3 
 1    2    3    2    3    4    5    6    7 

提前感谢您!

4个回答

3

一个想法可以是,

library(dplyr)
library(tidyr)

data.frame(mat) %>% 
 tibble::rownames_to_column('id') %>% 
 pivot_longer(-1) %>% 
 filter(value != 0) %>% 
 unite(key, name, id, sep = '=')

# A tibble: 9 x 2
  key   value
  <chr> <dbl>
1 a=x1      1
2 a=x2      2
3 a=x3      3
4 b=y1      2
5 b=y2      3
6 b=y3      4
7 c=z1      5
8 c=z2      6
9 c=z3      7

2
我们也可以使用asplitunlist它(但会得到.而不是=):
red <- unlist(asplit(mat, 2))
red <- red[red != 0]

输出:

a.x1 a.x2 a.x3 b.y1 b.y2 b.y3 c.z1 c.z2 c.z3 
   1    2    3    2    3    4    5    6    7 

当然,你也可以使用一些正则表达式(由@ user321797建议)来精确获得所需的输出 - 尽管这会牺牲一定的优雅。

names(red) <- gsub(names(red), pattern = "\\.", replacement = "=")

输出:

a=x1 a=x2 a=x3 b=y1 b=y2 b=y3 c=z1 c=z2 c=z3 
   1    2    3    2    3    4    5    6    7 

2

通过使用 which(..., arr.ind = TRUE) 的基础解决方案:

ind <- which(mat != 0, arr.ind = TRUE)
setNames(
  mat[ind],
  paste(colnames(mat)[ind[, 'col']], rownames(mat)[ind[, 'row']], sep = '=')
)

# a=x1 a=x2 a=x3 b=y1 b=y2 b=y3 c=z1 c=z2 c=z3 
#    1    2    3    2    3    4    5    6    7

1

这里有一个使用 deframe()tidyverse 解决方案:

library(tidyverse)

data.frame(mat) %>% 
  rownames_to_column() %>% 
  pivot_longer(-rowname) %>% 
  mutate(names = paste(name, rowname, sep="="), .keep="unused", .before=1) %>% 
  filter(value !=0) %>% 
  deframe()

a=x1 a=x2 a=x3 b=y1 b=y2 b=y3 c=z1 c=z2 c=z3 
   1    2    3    2    3    4    5    6    7 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接