优化填充矩阵的速度
Optimizing Speed for Populating a Matrix
我试图在 R 中填充一个最终将对称的大矩阵(55920484 个元素)(因此我实际上只对矩阵的一半执行计算)。结果值矩阵是一个方阵,具有相同的行名和列名。矩阵中的每个值都是比较唯一列表和计算交叉点数的结果。此数据来自更大的数据框 (427.5 Mb)。到目前为止,这是我最快的解决方案,我试图摆脱我知道很慢的循环:
for(i in 1:length(rownames(values))){
for(j in i:length(colnames(values))){
A = data[data$Stock==rownames(values)[i],"Fund"]
B = data[data$Stock==colnames(values)[j],"Fund"]
values[i, j] = length(intersect(A, B))
}
}
我尝试了其他几种方法,例如使用具有 SQL 连接的数据库、使用具有 0 和 1 的稀疏矩阵以及使用 R 中的 sqldf 包。
这是我的数据结构:
head(data)
Fund Stock Type Shares.Held Maket.Value X..of.Portfolio Rank Change.in.Shares X..Change X..Ownership
1 12 WEST CAPITAL MANAGEMENT LP GRUB CALL 500000 12100000 0.0173 12 500000 New N/A
2 12 WEST CAPITAL MANAGEMENT LP FIVE SH 214521 6886000 0.0099 15 214521 New 0
3 12 WEST CAPITAL MANAGEMENT LP SHAK SH 314114 12439000 0.0178 11 307114 4387 1
4 12 WEST CAPITAL MANAGEMENT LP FRSH SH 324120 3650000 0.0053 16 -175880 -35 2
5 12 WEST CAPITAL MANAGEMENT LP ATRA SH 393700 10398000 0.0149 14 162003 69 1
6 12 WEST CAPITAL MANAGEMENT LP ALNY SH 651000 61285000 0.0875 4 No Change 0 1
我看到三个问题,按重要性递增的顺序排列:
(1) 您多次调用 rownames(values) 和 colnames(values),而不是在循环外只调用一次。它可能有帮助也可能没有帮助。
(2) 你在最里面的循环下计算A = data[data$Stock==rownames(values)[i],"Fund"]
,而你应该在这个循环外计算它。
(3) 最重要的是:您的代码仅使用 table 的两列:基金和股票。我看到在您的数据中有很多行的基金和股票都相同。您应该消除这种冗余。也许您想创建 data1=data[,c("Fund","Stock")]
并消除 data1 中的冗余行(无循环):
data1 = data1[,order(data1[,"Fund"])]
len = nrow(data1)
good = c(TRUE,data1[-len,1]!=data1[-1,1]|data1[-len,2]!=data1[-1,2])
data1 = data1[good,]
(我没有测试上面的代码)
也许您想更进一步,创建列表,其中针对每个基金指定其包含的股票,没有冗余。
PS:您仍然可以创建列表,为每只股票指定哪些基金拥有它:
rv = rownames(values)
len = length(rv)
fund.list = list()
for (i in 1:len)
fund.list[[,i]] = data[data$Stock==rv[i],"Fund"]
for (i in 1:len) {
A = fund.list[[i]]
for (j in i:len) {
values[i, j] = length(intersect(A, fund.list[[j]]))
}
}
我试图在 R 中填充一个最终将对称的大矩阵(55920484 个元素)(因此我实际上只对矩阵的一半执行计算)。结果值矩阵是一个方阵,具有相同的行名和列名。矩阵中的每个值都是比较唯一列表和计算交叉点数的结果。此数据来自更大的数据框 (427.5 Mb)。到目前为止,这是我最快的解决方案,我试图摆脱我知道很慢的循环:
for(i in 1:length(rownames(values))){
for(j in i:length(colnames(values))){
A = data[data$Stock==rownames(values)[i],"Fund"]
B = data[data$Stock==colnames(values)[j],"Fund"]
values[i, j] = length(intersect(A, B))
}
}
我尝试了其他几种方法,例如使用具有 SQL 连接的数据库、使用具有 0 和 1 的稀疏矩阵以及使用 R 中的 sqldf 包。
这是我的数据结构:
head(data)
Fund Stock Type Shares.Held Maket.Value X..of.Portfolio Rank Change.in.Shares X..Change X..Ownership
1 12 WEST CAPITAL MANAGEMENT LP GRUB CALL 500000 12100000 0.0173 12 500000 New N/A
2 12 WEST CAPITAL MANAGEMENT LP FIVE SH 214521 6886000 0.0099 15 214521 New 0
3 12 WEST CAPITAL MANAGEMENT LP SHAK SH 314114 12439000 0.0178 11 307114 4387 1
4 12 WEST CAPITAL MANAGEMENT LP FRSH SH 324120 3650000 0.0053 16 -175880 -35 2
5 12 WEST CAPITAL MANAGEMENT LP ATRA SH 393700 10398000 0.0149 14 162003 69 1
6 12 WEST CAPITAL MANAGEMENT LP ALNY SH 651000 61285000 0.0875 4 No Change 0 1
我看到三个问题,按重要性递增的顺序排列:
(1) 您多次调用 rownames(values) 和 colnames(values),而不是在循环外只调用一次。它可能有帮助也可能没有帮助。
(2) 你在最里面的循环下计算A = data[data$Stock==rownames(values)[i],"Fund"]
,而你应该在这个循环外计算它。
(3) 最重要的是:您的代码仅使用 table 的两列:基金和股票。我看到在您的数据中有很多行的基金和股票都相同。您应该消除这种冗余。也许您想创建 data1=data[,c("Fund","Stock")]
并消除 data1 中的冗余行(无循环):
data1 = data1[,order(data1[,"Fund"])]
len = nrow(data1)
good = c(TRUE,data1[-len,1]!=data1[-1,1]|data1[-len,2]!=data1[-1,2])
data1 = data1[good,]
(我没有测试上面的代码)
也许您想更进一步,创建列表,其中针对每个基金指定其包含的股票,没有冗余。
PS:您仍然可以创建列表,为每只股票指定哪些基金拥有它:
rv = rownames(values)
len = length(rv)
fund.list = list()
for (i in 1:len)
fund.list[[,i]] = data[data$Stock==rv[i],"Fund"]
for (i in 1:len) {
A = fund.list[[i]]
for (j in i:len) {
values[i, j] = length(intersect(A, fund.list[[j]]))
}
}