我有一个data.frame
sources <- c("a", "b", "c", "a", "a", "b")
targets <- c("f", "v", "w", "a", "b", "c")
values <- c(12, 34, 56, 3, 76, 35)
df <- data.frame(sources, targets, values)
sources targets values
1 a f 12
2 b v 34
3 c w 56
4 a a 3
5 a b 76
6 b c 35
如何重塑它,以获得一个矩阵与源作为行名,目标作为colname和相交单元格的相应值?在这种情况下,我应该有一个3 × 6矩阵。像这样:
f v w a b c
a 12 0 0 3 76 0
b 0 34 0 0 0 35
c 0 0 56 0 0 0
您可以使用xtabs()
:
xtabs(values ~ sources + targets, df)
# a b c f v w
# a 3 76 0 12 0 0
# b 0 0 35 0 34 0
# c 0 0 0 0 0 56
如果您想要输出data.frame
,只需将其传递给as.data.frame.matrix()
。
我们可以使用矩阵索引。
sources <- c("a", "b", "c", "a", "a", "b")
targets <- c("f", "v", "w", "a", "b", "c")
values <- as.numeric(c(12, 34, 56, 3, 76, 35))
rn <- unique(sources)
cn <- unique(targets)
mat <- matrix(0, length(rn), length(cn), dimnames = list(rn, cn))
mat[cbind(sources, targets)] <- values
mat
# f v w a b c
#a 12 0 0 3 76 0
#b 0 34 0 0 0 35
#c 0 0 56 0 0 0
另一种与xtabs
类似的方法是
tapply(values, list(sources, targets), FUN = sum, default = 0)
# a b c f v w
#a 3 76 0 12 0 0
#b 0 0 35 0 34 0
#c 0 0 0 0 0 56
我认为xtabs
和tapply
是简洁的。但是我不喜欢factor()
在底层的强制。
你可以试试
library(tidyverse)
df <- data.frame(sources, targets, values)
df %>%
pivot_wider(names_from = targets, values_from = values) %>%
replace(is.na(.), 0) %>%
column_to_rownames(var = "sources")
f v w a b c
a 12 0 0 3 76 0
b 0 34 0 0 0 35
c 0 0 56 0 0 0
稀疏矩阵
如果期望得到的矩阵是稀疏的(并且很大),那么您可能希望直接转换为稀疏矩阵数据结构。这可以通过将source
和target
项转换为因子来帮助实现。
library(magrittr)
library(Matrix)
df['sources'] <- factor(df$sources)
df['targets'] <- factor(df$targets)
df %$%
sparseMatrix(i=as.integer(sources),
j=as.integer(targets),
x=values,
dimnames=list(sources=levels(sources),
targets=levels(targets)))
结果是
3 x 6 sparse Matrix of class "dgCMatrix"
targets
sources a b c f v w
a 3 76 . 12 . .
b . . 35 . 34 .
c . . . . . 56
可以通过在因子转换中指定levels
来控制行和列的顺序。请注意magrittr
的展示管道(%$%
)的使用。