从数据框中创建方阵

6

我想把我的数据框转换为方阵,但是遇到了一些问题。 现在我的数据看起来像这样:

  var1 var2 value
    A    B     4
    C    D     5 
    D    A     2
    B    D     1

我将尝试将数据框转换为以下样式的矩阵:
    A    B    C   D
  A 0    4    0   2
  B 4    0    0   1
  C 0    0    0   5
  D 2    1    5   0

我尝试了R中不同包中的许多函数,但仍然找不到解决方案。

请发布您尝试过的许多函数以及为什么它们没有起作用。 - pogibas
1
xtabs(value~var1+var2, df) - Sotos
1
@Sotos 这会错过列 C - pogibas
谢谢你尝试帮助我。 @PoGibas 我尝试了这个代码:comatrix <- data.frame(var1 = data3$u1.var1, scores = data3$value, var2= factor(data3$var2,levels=unique(data3$var2))) acast(comatrix, formula = var1 ~ var2, fill = 0, value.var ="scores", fun.aggregate =sum, drop = FALSE) 通过这段代码,我得到了一个矩阵,但不是方阵。 - Brenna
2个回答

8
这里是一个使用矩阵索引对字符向量进行操作的基本R语言方法。
## set up storage matrix
# get names for row and columns
nameVals <- sort(unique(unlist(dat[1:2])))
# construct 0 matrix of correct dimensions with row and column names
myMat <- matrix(0, length(nameVals), length(nameVals), dimnames = list(nameVals, nameVals))

# fill in the matrix with matrix indexing on row and column names
myMat[as.matrix(dat[c("var1", "var2")])] <- dat[["value"]]

这将返回

myMat
  A B C D
A 0 4 0 0
B 0 0 0 1
C 0 0 0 5
D 2 0 0 0

关于这种强大的索引形式的详细信息,请参见帮助文件?"["中的矩阵和数组部分。特别是该部分的第四段讨论了这种索引形式。

请注意,我假设前两个变量是字符向量而不是因子。这使得它稍微容易一些,因为我不必使用as.character来强制转换它们。

要将结果转换为数据框,请简单地使用as.data.frame函数包装上述代码。

数据

dat <- 
structure(list(var1 = c("A", "C", "D", "B"), var2 = c("B", "D", 
"A", "D"), value = c(4L, 5L, 2L, 1L)), .Names = c("var1", "var2", 
"value"), class = "data.frame", row.names = c(NA, -4L))

5

如果我们将所有的字符列都变成因子,使用水平为“A”、“B”、“C”、“D”的级别,那么我们就可以在不删除任何列的情况下使用“xtabs”。

不幸的是,得到的矩阵并不对称。

library('tidyverse')

df <- tribble(
  ~var1, ~var2, ~value,
    'A',   'B',      4,
    'C',   'D',      5,
    'D',   'A',      2,
    'B',   'D',      1
)

df %>%
  mutate_if(is.character, factor, levels=c('A', 'B', 'C', 'D')) %>%
  xtabs(value ~ var1 + var2, ., drop.unused.levels = F)
#     var2
# var1 A B C D
#    A 0 4 0 0
#    B 0 0 0 1
#    C 0 0 0 5
#    D 2 0 0 0

为使其对称,我只需将其转置并加到自身。虽然这感觉有点像一个技巧。
df %>%
  mutate_if(is.character, factor, levels=c('A', 'B', 'C', 'D')) %>%
  xtabs(value ~ var1 + var2, ., drop.unused.levels = F) %>%
  '+'(., t(.))
#     var2
# var1 A B C D
#    A 0 4 0 2
#    B 4 0 0 1
#    C 0 0 0 5
#    D 2 1 5 0

这感觉有点像是一个hack,虽然这在R中是许多好的解决方案都可以使用的。+1 - John Coleman
感谢您的详细回复@Paul。但实际上,我仍然有一个问题,因为我将我的变量存储在数据框中。 df <- tribble(~var1,~var2,~score,data3$var1,data3$var2,data3$score) df %>% mutate_if(is.character, factor, levels=c('data3$var1','data3$var2')) %>% xtabs(score ~ var1 + var2,., drop.unused.levels = F) %>% '+'(., t(.)) - Brenna
你正在使用tribble的方式会导致列表列。你可以直接使用data3 %>% mutate_if(is.character, factor, levels=c('A', 'B', 'C', 'D')) %>% xtabs(score ~ var1 + var2, ., drop.unused.levels = F) %>% '+'(., t(.)) - Paul

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