如何创建包含全部节点但仅对应年份边子集的network对象?
问题描述
我用下面的代码创建网络:
library(network) ###create a network edges_list <- lapply(eyears, function(x){network(edges[edges$Year_n <= x ,1:2],directed = FALSE, vertex.attr = nodes)})
其中:
eyears是Year_n的向量edges是首列为from和to列的数据框nodes是首列为nodeID(与from和to列匹配)的数据框
我需要调整代码,让edges_list的每个元素都包含全部节点以及对应年份的边。
数据结构信息
str(eyears) num [1:9] 1974 1976 1978 1980 1982 ... dput(eyears) c(1974, 1976, 1978, 1980, 1982, 1984, 1986, 1988, 1990) str(edges) 'data.frame': 524 obs. of 8 variables: $ from : int 212 208 210 214 215 295 212 209 136 64 ... $ to : int 208 210 214 215 291 290 209 136 133 60 ... $ cat : num 1 2 3 4 5 6 7 8 9 10 ... $ Year : num 1975 1978 1980 1980 1981 ... $ global: num NA NA NA NA NA NA NA NA NA NA ... $ length: num 98624 15078 232283 199234 78635 ... $ PLAN : num 0 0 0 0 0 0 0 1 1 1 ... $ Year_n: num 1975 1978 1980 1980 1981 ... dput(edges[1:10, 1:8]) structure(list(from = c(212L, 208L, 210L, 214L, 215L, 295L, 212L, 209L, 136L, 64L), to = c(208L, 210L, 214L, 215L, 291L, 290L, 209L, 136L, 133L, 60L), cat = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ), Year = c(1975, 1978, 1980, 1980, 1981, 1981, 1975, 1972, 1972, 1977), global = c(NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), length = c(98623.6375924798, 15077.7144003721, 232283.331561727, 199233.502207442, 78635.0389206188, 131367.696300722, 37153.912532765, 56431.0393784146, 42069.0250811096, 94832.0618165286), PLAN = c(0, 0, 0, 0, 0, 0, 0, 1, 1, 1), Year_n = c(1975, 1978, 1980, 1980, 1981, 1981, 1974, 1972, 1972, 1976)), row.names = c(NA, 10L), class = "data.frame") dput(nodes[1:5, 1:8]) structure(list(nodeID = c(212L, 208L, 210L, 214L, 215L), geometry = structure(list( structure(c(2.41222419606553, 6.37236234905488), class = c("XY", "POINT", "sfg")), structure(c(2.06074739865659, 7.18774854505763 ), class = c("XY", "POINT", "sfg")), structure(c(2.08122414661067, 7.32181538325724), class = c("XY", "POINT", "sfg")), structure(c(2.62560447031769, 9.34015700977641), class = c("XY", "POINT", "sfg")), structure(c(2.85342785762295, 11.1178227489884), class = c("XY", "POINT", "sfg"))), class = c("sfc_POINT", "sfc"), precision = 0, bbox = structure(c(xmin = 2.06074739865659, ymin = 6.37236234905488, xmax = 2.85342785762295, ymax = 11.1178227489884 ), class = "bbox"), crs = structure(list(input = "GCS_WGS_84_CRS84", wkt = "GEOGCRS[\"GCS_WGS_84_CRS84\",\n DATUM[\"World Geodetic System 1984\",\n ELLIPSOID[\"WGS 84\",6378137,298.257223563,\n LENGTHUNIT[\"metre\",1]],\n ID[\"EPSG\",6326]],\n PRIMEM[\"Greenwich\",0,\n ANGLEUNIT[\"Degree\",0.0174532925199433]],\n CS[ellipsoidal,2],\n AXIS[\"longitude\",east,\n ORDER[1],\n ANGLEUNIT[\"Degree\",0.0174532925199433]],\n AXIS[\"latitude\",north,\n ORDER[2],\n ANGLEUNIT[\"Degree\",0.0174532925199433]]]"), class = "crs"), n_empty = 0L), mother1946 = c("FRA", "FRA", "FRA", "FRA", "FRA"), country_name = c("Benin", "Benin", "Benin", "Benin", "Benin"), iso3c = c("BEN", "BEN", "BEN", "BEN", "BEN"), dist2river = c(206.4402, 200.9958, 201.0137, 212.8585, 98.41196), dist2coast = c(0, 88.95607, 111.1951, 331.5523, 525.4953), dist2emst = c(12.10693, 3.912999, 19.6633, 39.41241, 233.1657)), row.names = c(NA, -5L), sf_column = "geometry", agr = structure(c(nodeID = NA_integer_, mother1946 = NA_integer_, country_name = NA_integer_, iso3c = NA_integer_, dist2river = NA_integer_, dist2coast = NA_integer_, dist2emst = NA_integer_ ), levels = c("constant", "aggregate", "identity"), class = "factor"), class = c("sf", "tbl_df", "tbl", "data.frame"))
解决方案
原代码的问题是network()函数默认只保留边数据中出现的节点,不会自动包含所有节点。要强制包含全部节点,需要指定vertices参数传入所有节点ID,同时保留节点属性。
修改后的代码如下:
library(network) # 提取所有节点ID all_nodes <- nodes$nodeID # 创建包含全部节点的网络列表 edges_list <- lapply(eyears, function(x){ # 筛选当前年份及之前的边 filtered_edges <- edges[edges$Year_n <= x, c("from", "to")] # 创建网络:指定vertices包含所有节点,同时传入节点属性 network(filtered_edges, directed = FALSE, vertices = all_nodes, vertex.attr = nodes, vertex.attrnames = colnames(nodes)) })
关键说明
vertices = all_nodes:强制网络包含所有节点,即使部分节点在当前年份没有关联边vertex.attr = nodes:保留节点的所有属性数据vertex.attrnames = colnames(nodes):显式指定属性列名,避免列名匹配异常导致属性丢失
你可以用以下代码验证每个网络是否包含全部节点:
# 检查第一个网络的节点数是否等于总节点数 length(edges_list[[1]]$val$vertex.names) == nrow(nodes)
内容的提问来源于stack exchange,提问作者Sulz
相关产品推荐
相关产品推荐

