如何用igraph基于双变量公共值重塑数据及解决图构建问题
基于igraph的数据集关联合并问题解决
需求说明
当一条记录的var3与另一条记录的var2相等时,将两条记录关联合并:保留起始记录的var1和var2,将var3替换为关联链末端记录的var3;连续相同var1的记录也遵循此规则。
示例数据集
原始数据:
| var1 | var2 | var3 |
|---|---|---|
| a | 1 | 2 |
| b | 2 | 3 |
| b | 3 | 5 |
| b | 7 | 9 |
| c | 5 | 9 |
期望结果:
| var1 | var2 | var3 |
|---|---|---|
| a | 1 | 5 |
| b | 7 | 9 |
| c | 5 | 9 |
现有代码问题
使用igraph处理时,执行以下代码后,图表仅显示var2节点,var3被当作边属性忽略:
library(igraph) df = structure(list(var1 = c("a", "b", "b", "b", "c"), var2 = c(1L, 2L, 3L, 7L, 5L), var3 = c(2L, 3L, 5L, 9L, 9L)), class = "data.frame", row.names = c(NA, -5L)) g <- graph_from_data_frame(df)
存在两个疑问:
- 如何连接名称不同的节点(如a和b)?
- 如何在图中加入
var3变量作为节点?
解决方案
疑问2:将var3作为节点加入图中
graph_from_data_frame默认将第一列作为起点节点、第二列作为终点节点,后续列作为边属性。要让var3成为节点,需重新构造边列表:将每条记录的var2作为起点、var3作为终点,同时把var1作为边的属性。
library(igraph) # 原始数据 df <- structure(list(var1 = c("a", "b", "b", "b", "c"), var2 = c(1L, 2L, 3L, 7L, 5L), var3 = c(2L, 3L, 5L, 9L, 9L)), class = "data.frame", row.names = c(NA, -5L)) # 构造边列表:var2 -> var3,携带var1属性 edges <- df[, c("var2", "var3")] edges$var1 <- df$var1 # 构建有向图 g <- graph_from_data_frame(d = edges, directed = TRUE) # 查看所有节点(包含var2和var3的数值) print(V(g)) # 查看边的var1属性 print(E(g)$var1)
疑问1:连接不同名称的节点(如a和b)
不同字符节点(a、b、c)需要通过数值节点作为中间桥梁关联:
- 当记录a的
var3=2与记录b的var2=2相等时,数值节点2会成为连接a和b的中间节点; - 可以额外添加
var1到var2、var1到var3的边,明确字符节点与数值节点的关联:
# 添加var1与数值节点的关联边 var1_edges <- rbind( data.frame(from = df$var1, to = as.character(df$var2), var1 = df$var1), data.frame(from = df$var1, to = as.character(df$var3), var1 = df$var1) ) # 合并所有边 all_edges <- rbind(edges, var1_edges) # 重新构建图 g_full <- graph_from_data_frame(d = all_edges, directed = TRUE) # 此时a和b会通过数值节点2连通 print(are_connected(g_full, "a", "b")) # 返回TRUE
完整合并实现
通过图的连通性找到每条记录的关联链末端,最终合并得到目标数据集:
# 定义函数:找到节点可达的最远数值节点 get_furthest_end <- function(start_node) { # 获取所有可达节点 reachable_nodes <- reachable(g, start_node, mode = "out") # 转换为数值并取最大值(即链的末端) furthest <- max(as.numeric(reachable_nodes)) return(as.character(furthest)) } # 为每条记录的var2找到对应的最远var3 df$new_var3 <- sapply(as.character(df$var2), get_furthest_end) # 按var1分组,保留最早的var2和最远的new_var3 library(dplyr) result <- df %>% group_by(var1) %>% summarise( var2 = first(var2), var3 = last(new_var3) # 分组后最后一个new_var3是最远的关联终点 ) %>% ungroup() # 查看结果 print(result)
运行后得到的结果与期望一致:
# A tibble: 3 × 3 var1 var2 var3 <chr> <int> <chr> 1 a 1 5 2 b 7 9 3 c 5 9
内容的提问来源于stack exchange,提问作者doraemon
相关产品推荐
相关产品推荐

