是否有R函数可重构igraph网络分析用的共病患者数据?
R实现共病数据转无向边表并统计边频
一、专用函数实现:igraph的二分图投影
最直接的方法是利用igraph的bipartite_projection函数,从患者-疾病的关联矩阵直接生成疾病共现网络,自动统计无向边的共现次数:
步骤1:准备数据
假设你的宽表数据结构如下(id为患者ID,com1-com4为疾病列,1表示患病):
# 模拟示例数据 set.seed(123) df <- data.frame( id = paste0("id", sprintf("%03d", 1:10)), com1 = sample(c(0,1), 10, replace = TRUE), com2 = sample(c(0,1), 10, replace = TRUE), com3 = sample(c(0,1), 10, replace = TRUE), com4 = sample(c(0,1), 10, replace = TRUE) )
步骤2:生成二分图并投影
library(igraph) # 提取患者-疾病的关联矩阵(去掉ID列) incidence_mat <- as.matrix(df[, -1]) # 创建二分图(患者为一类节点,疾病为另一类节点) bipartite_graph <- graph_from_incidence_matrix(incidence_mat, directed = FALSE) # 投影生成疾病间的共现网络,边权重为共病的患者数 disease_cooccur_graph <- bipartite_projection(bipartite_graph, which = "true") # 导出带权重的无向边表 edge_counts <- as_data_frame(disease_cooccur_graph, what = "edges")
得到的edge_counts包含from、to、weight三列,其中weight就是两种疾病共现的患者次数,且自动处理了无向边的顺序(不会出现com1-com2和com2-com1重复的情况)。
二、手动实现:dplyr+purrr组合
如果需要更灵活的自定义处理,可以用dplyr和purrr逐行生成边并统一无向边顺序:
步骤1:生成原始边表
library(dplyr) library(purrr) edge_list <- df %>% # 筛选有2种及以上共病的患者 filter(rowSums(select(., starts_with("com"))) >= 2) %>% rowwise() %>% # 提取当前患者的所有患病名称 mutate(diseases = list(names(select(., starts_with("com")))[c_across(starts_with("com")) == 1])) %>% # 生成所有两两疾病组合 mutate(edges = list(t(combn(diseases, 2)))) %>% unnest(edges) %>% # 统一无向边顺序:让node1始终小于node2(按字符排序) mutate( node1 = pmin(edges[,1], edges[,2]), node2 = pmax(edges[,1], edges[,2]) ) %>% select(id, node1, node2)
步骤2:统计边的出现次数
edge_counts <- edge_list %>% group_by(node1, node2) %>% summarise(weight = n(), .groups = "drop")
三、可视化疾病关联网络
用生成的edge_counts直接创建igraph对象并可视化:
g <- graph_from_data_frame(edge_counts, directed = FALSE) # 自定义样式:边宽对应权重,节点大小对应疾病度数 E(g)$width <- E(g)$weight * 2 V(g)$size <- degree(g) * 5 plot(g, edge.label = E(g)$weight, # 显示边的权重 vertex.label.cex = 1.2, # 节点标签大小 layout = layout_with_fr) # 用Fruchterman-Reingold布局
内容的提问来源于stack exchange,提问作者jacbin76
相关产品推荐
相关产品推荐

