该问题源于disparityfilter包中的一个错误。由backbone()
调用的disparity_filter
函数的内部涉及将节点名称与节点索引(一个bug)进行比较,并且因此该函数仅在节点名称碰巧等于节点索引时才起作用。清楚的是,这意味着在一般情况下(例如你的例子b),结果是,无论如何都可能是错误的--尽管有些东西正在返回。
将索引与名称进行比较是函数不返回任何含有字符的原因,也是它不返回任何大数字的原因:如果数字的大小超过了网络匹配中的节点数从不发生。
我将演示,然后指出问题出现在代码中的位置。然后,我会很快显示结果与当前存在的代码版本的不同以及导致“正确”输出的快速“修复”(丑陋的黑客攻击)有多不同(我是吓人的引用是正确的,吨真的知道输出应该是什么或如何测试)。
复制您发现
OK,你的网络文件的链接被打破,所以我会从igraphdata
包中使用的一些数据:
# Load the requisite libraries
library(igraph)
library(disparityfilter)
library(igraphdata)
# We'll use the enron email network (b/c cool)
data(enron)
# convert it to a df
df <- igraph::as_data_frame(enron, what = 'edges')
summary(df) # we see nodes numbered from 1:184
#> from to Time Reciptype
#> Min. : 1.0 Min. : 1 Length:125409 Length:125409
#> 1st Qu.: 64.0 1st Qu.: 64 Class :character Class :character
#> Median :108.0 Median :113 Mode :character Mode :character
#> Mean :105.4 Mean :108
#> 3rd Qu.:156.0 3rd Qu.:156
#> Max. :184.0 Max. :184
#> Topic LDC_topic
#> Min. :0.000 Min. :-1.000
#> 1st Qu.:1.000 1st Qu.: 0.000
#> Median :1.000 Median : 0.000
#> Mean :1.711 Mean : 2.572
#> 3rd Qu.:3.000 3rd Qu.: 1.000
#> Max. :3.000 Max. :32.000
# create a weights variable
df$weight <- df$Topic
现在让我们创建字符和large-顶点名称的数字版本
# Create a char version of the nodes by appending 'char' to the number
dfchar <- df
dfchar$from <- paste0("char", dfchar$from)
dfchar$to <- paste0("char", dfchar$to)
# create a big num version
dfbnum <- df
dfbnum$from <- 1000 * dfbnum$from
dfbnum$to <- 1000 * dfbnum$to
现在我们将data.frames转换回gr APHS
# Now convert the DFs back to graphs
smallnum <- graph_from_data_frame(df, directed = TRUE)
chars <- graph_from_data_frame(dfchar, directed = TRUE)
bignum <- graph_from_data_frame(dfbnum, directed = TRUE)
然后,我们可以在整个这三个图形backbone()
复制你发现了什么:
## Now we document what you found: namely the anomolous behavior of backbone
newbbs <- backbone(smallnum)
dim(newbbs)
#> [1] 231 4
newbbc <- backbone(chars)
dim(newbbc)
#> [1] 0 4
newbbb <- backbone(bignum)
dim(newbbb)
#> [1] 0 4
因此,正如你提到的,甚至可以在其他数据backbone()
功能未找到匹配,除非节点标记一般为1:N
。
发现问题
好吧,至此我正在复制您记录的内容。我们如何知道backbone()
内的索引问题?首先让我告诉你会发生什么,如果我们使节点的名称比指数大了一点:
# now to demonstrate the indexing issue quickly, lets increment
# the node names just a bit, and see what gets returned.
# create a medium num version
dfmnum <- df
dfmnum$from <- dfmnum$from + 90 #add about half the number of nodes to the name
dfmnum$to <- dfmnum$to + 90
# convert back to graph
midnum <- graph_from_data_frame(dfmnum)
bbmid <- backbone(midnum)
dim(bbmid)
#> [1] 28 4
正如你可以看到这极大地改变了功能的性能 - 而不是找到231个结果我们”已经找到了28!原因是现在有一半的节点名称与索引没有匹配,大约有一半 - 所以我们得到了随机(并且完全不正确)的结果。
问题在哪里?
disparityfilter
软件包位于github上,由文件disparity_filter.R组成,文件disparity_filter.R可见here。在第58行,disparity_filter
函数将backbone()
中提供的图转换回数据帧。让我们做的是用图形的我们的“性格”版本:
e <- igraph::as_data_frame(chars)[,1:2]
head(e)
from to
1 char25 char154
2 char25 char154
3 char30 char30
4 char30 char30
5 char30 char30
6 char30 char30
正如我们从和列在这里有我们赋予他们的名字见。然后从行63开始,disparity_filter()
函数会循环使用行for (u in which(d > 1))
的程度(d
)大于1的情况。然后在第65行上switch
声明一系列比较的节点的名称和指数ü两种情况:
w = switch(substr(mode, 1, 1),
a = which(e[, 1] == u | e[, 2] == u),
i = which(e[, 2] == u),
o = which(e[, 1] == u)
)
这显然是不正确的,如果一个节点的名字碰巧才起作用匹配它的索引。为了明确起见,使用我们的chars
版本的图表,u
的第一个值将为1,对应于节点char25
。值char25
存在于向量e[,1]
中,但当然不会与索引匹配 - 尽管这是作者推测的意图。在第76行开始的switch()
语句中重复出现了同样的问题。由于没有匹配,当节点具有非数字名称或数字名称超过节点数时,不会返回任何结果。
问题有多严重?
好吧,那么节点的名称从一个起算的情况如何呢?让我们来看看u
和e[,1]
的值是什么。我们将使用图形的版本顶点的名字是“工作”:
d <- degree(smallnum)
which(d>1)
25 30 39 52 61 64 66 67 93 100 115 125 138 141 146 156 164 168 170
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
正如我们所看到的顶点的数值名称不对应的索引反正!所以即使在某些东西被返回的情况下,我们也只是回到噪音。快速编辑以查看差异;所以现在该指数相匹配的顶点
renamed <- set.vertex.attribute(smallnum, "name", value=1:length(V(smallnum)))
bbs_problem_revealed <- backbone(renamed)
dim(bbs_problem_revealed)
[1] 9 4
OK,我们只得到9个观察回:所以他们对应的指数,我们将重命名的顶点!显然,该功能有些问题。这个新答案是否正确?老实说,我不确定,因为我不确定输出应该是什么,或者我可以如何验证它。此外,如果我要依赖代码,我想真正重做比较以匹配名称和名称。
无论如何,我的建议是,除非软件包作者有机会修复它,否则不要使用这个函数。我将在github上打开一个bug报告。
我已经在几个月前在github上创建了一个bug报告,他们从未回复过。但事实上,你对相关部门的分析是正确的。我冒昧地根据'tidyverse'软件包自己创建一些代码,从而产生更接近原始发表的论文的结果。 – FilipeTeixeira
嗯这太糟糕了,他们没有解决它。 CRAN软件包的下载量为7k,但不应该以目前的形式真正使用。也许你可以在这里链接到你的算法工作版本(如果它在github上)那些搜索答案的人? – gfgm
我把它作为一个包的一部分,我一直在开发其他东西,可以在这里找到https://github.com/FilipeamTeixeira/skynet。但是,您可以将其作为单独的R文件在那里调用disparityfilter.R。这是一个相当简单的实现,但到目前为止它达到了目的,并且与原始论文的结果相匹配。 – FilipeTeixeira