根据下图,我想用$ name组合一些边。但是,通过基于它们所连接的顶点进行合并来简化图形很容易,但不能通过某个标签对它们进行分组,在本例中为$ name。
g <- graph(c(1,2, 1,2, 1,2, 2,3, 3,4))
E(g)$weight <- 1:5
E(g)$name <- c("A", "A", "B", "C", "D")
运行simplify
函数甚至as.directed\as.undirected
时,如果未在edge.attr.comb
参数上指定,则删除名称,这非常有意义。但至于指定,我只能选择max或min,或将其转换为字符串。
simplify(g, edge.attr.comb=list(weight = "sum")
我想要的结果是图表中用A标记的边合并/求和,但用B标记的边保持为平行边。 我尝试过几件事都没有成功。
编辑:我知道我可以将图形转换为数据框,将数据分组,然后返回图形。或者在将数据框放入图形之前简单地准备数据框。然而,这太过于摆弄,直接通过igraph更容易。
答案 0 :(得分:1)
您可以通过转换为数据框然后返回图表来执行此操作:
library(dplyr)
df <- igraph::as_data_frame(g)
df <- df %>% group_by(name) %>% mutate(weight = sum(weight)) %>% unique()
df
# A tibble: 4 x 4
# Groups: name [4]
from to weight name
<dbl> <dbl> <int> <chr>
1 1.00 2.00 3 A
2 1.00 2.00 3 B
3 2.00 3.00 4 C
4 3.00 4.00 5 D
g2 <- igraph::graph_from_data_frame(df)
抱歉刚回到这里。是的,我不认为确切的功能存在,这将是很好的。但您可以通过以下两个步骤完成:1)聚合具有共享名称的节点的权重,以及2.)删除重复的边缘
library(dplyr)
library(microbenchmark)
library(igraph)
g <- graph(c(1,2, 1,2, 1,2, 2,3, 3,4))
E(g)$weight <- 1:5
E(g)$name <- c("A", "A", "B", "C", "D")
首先将数据包装到data.frame并返回到函数中:
to_df_and_back <- function(g) {
df <- igraph::as_data_frame(g)
df <- df %>% group_by(name) %>% mutate(weight = sum(weight)) %>% unique()
g2 <- igraph::graph_from_data_frame(df)
g2
}
现在我们为另一种方法创建一个函数:首先重新计算边缘权重,然后将图形子集合成唯一命名的边缘ID:
add_then_subset <- function(g) {
E(g)$weight <- ave(E(g)$weight, names(E(g)), FUN=sum)
g2 <- subgraph.edges(g, eid = E(g)[unique(E(g)$name)])
g2
}
g1 <- to_df_and_back(g)
g2 <- add_then_subset(g)
identical(E(g1)$weight, E(g2)$weight)
#> [1] TRUE
这里的速度结果意味着重量级和子集策略的速度要快得多(中位数大约是时间的四分之一),但是你想要对你的数据进行测试,因为我不知道不知道它会如何扩展。
microbenchmark(to_df_and_back(g), add_then_subset(g))
#> Unit: milliseconds
#> expr min lq mean median uq max
#> to_df_and_back(g) 4.588584 4.851213 6.901448 4.947683 5.130546 182.82945
#> add_then_subset(g) 1.208795 1.314137 2.138570 1.382700 1.485809 70.16585
#> neval cld
#> 100 b
#> 100 a