制作稀疏矩阵时出错。

4
我遇到了一个我不理解的问题。这是对此处此处建议答案的跟进。
我有两个结构完全相同的数据集。一个我创建为可重现的示例,代码可以正常运行;另一个是真实数据集,代码无法运行。在盯着它看了几个小时后,我找不到导致错误的原因。以下是可以运行的示例:
    df <- data.table(cbind(rep(seq(1,25), each = 4 )), cbind(rep(seq(1,40), length.out = 100)))
    colnames(df) <- c("a", "b") #ignore warning
setkey(df, a, b)

我只是想创建一个可重复的示例。当我应用所提及的SO文章中建议的略微调整的代码时,我得到了我想要的东西:一个稀疏矩阵,指示列b中两个元素在列a的值下同时出现的情况。

library(Matrix)
s <- sparseMatrix(
  df$a,
  df$b,
    dimnames = list(
        unique(df$a),unique(df$b)), x = 1)
v <- t(s) %*% s

现在我正在处理我的真实数据集,这个数据集比较长,在我的眼中,我正在做完全相同的事情。

下面是一个dput的示例:

test <- dput(dk[1:50,])
structure(list(pid = c(204L, 204L, 207L, 254L, 254L, 258L, 258L, 
258L, 258L, 258L, 265L, 265L, 269L, 269L, 269L, 269L, 1520L, 
1520L, 1520L, 1520L, 1532L, 1532L, 1534L, 1534L, 1534L, 1534L, 
1539L, 1539L, 1543L, 1543L, 1546L, 1546L, 1546L, 1546L, 1546L, 
1546L, 1546L, 1549L, 1549L, 1549L, 1559L, 1559L, 1559L, 1559L, 
1559L, 1559L, 1559L, 1561L, 1561L, 1561L), cid = c(11023L, 11787L, 
14232L, 14470L, 14480L, 1290L, 1637L, 4452L, 13964L, 14590L, 
17814L, 23453L, 6658L, 10952L, 17259L, 27549L, 11034L, 22748L, 
23345L, 23347L, 10487L, 11162L, 15570L, 15629L, 17983L, 17999L, 
17531L, 22497L, 14425L, 14521L, 11495L, 24948L, 24962L, 24969L, 
24972L, 24973L, 30627L, 17886L, 18428L, 23972L, 13890L, 13936L, 
14432L, 21230L, 21271L, 21384L, 21437L, 341L, 354L, 6302L)), .Names = c("pid", 
"cid"), sorted = c("pid", "cid"), class = c("data.table", "data.frame"
), row.names = c(NA, -50L), .internal.selfref = <pointer: 0x0000000000100788>)

然后当我运行相同的公式时,出现了错误。

s <- sparseMatrix(test$pid,test$cid,dimnames = list(unique(test$pid), unique(test$cid)),x = 1)

错误信息(在test数据集中也会出现)如下:
Error in validObject(r) : 
  invalid class “dgTMatrix” object: length(Dimnames[[1]])' must match Dim[1]

如果我删除dimnames,问题就消失了,但我真的需要这些dimnames才能理解结果。我肯定错过了一些显而易见的东西。有人能告诉我是什么吗?

1个回答

1
我们可以将“pid”和“cid”列转换为因子,然后强制转换回数字,或者使用match与每列的唯一值获取行/列索引,这应该可以创建sparseMatrix
test1 <- test[, lapply(.SD, function(x) 
                 as.numeric(factor(x, levels=unique(x))))]

或者我们使用match
test1 <- test[, lapply(.SD, function(x) match(x, unique(x)))]

s1 <- sparseMatrix(test1$pid,test1$cid,dimnames = list(unique(test$pid), 
                 unique(test$cid)),x = 1)
dim(s1)
#[1] 15 50

s1[1:3, 1:3]
#3 x 3 sparse Matrix of class "dgCMatrix"
#    11023 11787 14232
#204     1     1     .
#207     .     .     1
#254     .     .     .

head(test)
#   pid   cid
#1: 204 11023
#2: 204 11787
#3: 207 14232
#4: 254 14470
#5: 254 14480
#6: 258  1290

编辑:

如果我们想要针对“test”中指定的完整行/列索引,我们需要将dimnames长度与'pid'、'cid'的max相同。

rnm <- seq(max(test$pid))
cnm <- seq(max(test$cid))
s2 <- sparseMatrix(test$pid, test$cid, dimnames=list(rnm, cnm))
dim(s2)
#[1]  1561 30627
s2[1:3, 1:3]
#3 x 3 sparse Matrix of class "ngCMatrix"
# 1 2 3
#1 . . .
#2 . . .
#3 . . .

谢谢@Akrun,这似乎可以工作,但我仍然感到困惑。这个解决方法所需的原因是因为sparseMatrix需要完美地跟随彼此的变量(如分配的因素1,2,3,4,5,6,7...),并且它不能使用像我在'dput'中拥有的不那么有序的数字吗?如果是这样,是否有任何限制的原因? - SJDS
@simon_icl 尺寸与维度名称的长度不匹配。例如 dim(sparseMatrix(i=test$pid[1:5], j=test$cid[1:5], x=1)) #[1] 254 14480,而在dimnames中我们提供了length(unique(test$pid[1:5])) #[1] 3。这必须匹配。另一种方法是将dimnames创建为pid和cid唯一值的最小值:最大值序列。 - akrun
@simon_icl 更新了帖子。你能检查一下是否有效吗? - akrun
我发现这个问题在维度上发生了,但我不明白为什么在两个给定的例子之间会有差异。唯一明显的区别似乎在于每个维度的唯一值的顺序,第一个例子中唯一值的顺序是从低到高,而第二个例子则不然。你的解决方案可行,所以我可以继续进行,但我试图理解为什么sparseMatrix需要这个顺序。简单地用list(ordered(unique(dk$pid)), ordered(unique(dk$cid)))替换我的解决方案并不起作用...另外,虽然我可以复制你的尺寸结果,但它们怎么可能这么大呢? - SJDS
啊哈,现在突然非常清楚了!感谢你的耐心和详细的解释,伙计! - SJDS
显示剩余2条评论

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