Skip to content

Commit e8523db

Browse files
committed
Accept numeric edge IDs
1 parent 9b06810 commit e8523db

File tree

2 files changed

+65
-58
lines changed

2 files changed

+65
-58
lines changed

R/data_frame.R

Lines changed: 61 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -100,16 +100,17 @@ graph.data.frame <- function(d, directed = TRUE, vertices = NULL) { # nocov star
100100
#' is returned, in a list with named entries `vertices` and `edges`.
101101
#'
102102
#' @param d A data frame containing a symbolic edge list in the first two
103-
#' columns. Additional columns are considered as edge attributes. Since
103+
#' columns, as vertex names or vertex IDs.
104+
# Additional columns are considered as edge attributes. Since
104105
#' version 0.7 this argument is coerced to a data frame with
105-
#' `as.data.frame`.
106+
#' [as.data.frame()].
106107
#' @param directed Logical scalar, whether or not to create a directed graph.
107108
#' @param vertices A data frame with vertex metadata, or `NULL`. See
108109
#' details below. Since version 0.7 this argument is coerced to a data frame
109-
#' with `as.data.frame`, if not `NULL`.
110+
#' with [as.data.frame()], if not `NULL`.
110111
#' @return An igraph graph object for `graph_from_data_frame()`, and either a
111112
#' data frame or a list of two data frames named `edges` and
112-
#' `vertices` for `as.data.frame`.
113+
#' `vertices` for [as.data.frame()].
113114
#' @note For `graph_from_data_frame()` `NA` elements in the first two
114115
#' columns \sQuote{d} are replaced by the string \dQuote{NA} before creating
115116
#' the graph. This means that all `NA`s will correspond to a single
@@ -155,82 +156,88 @@ graph.data.frame <- function(d, directed = TRUE, vertices = NULL) { # nocov star
155156
#' @export
156157
graph_from_data_frame <- function(d, directed = TRUE, vertices = NULL) {
157158
d <- as.data.frame(d)
158-
if (!is.null(vertices)) {
159+
if (is.character(vertices) || is.factor(vertices)) {
160+
vertices <- data.frame(name = as.character(vertices))
161+
} else if (is.matrix(vertices)) {
159162
vertices <- as.data.frame(vertices)
163+
} else if (!is.null(vertices) && !is.data.frame(vertices)) {
164+
stop("`vertices` must be a data frame or a character vector if given")
160165
}
161166

162167
if (ncol(d) < 2) {
163-
stop("the data frame should contain at least two columns")
168+
stop("`d` should contain at least two columns")
164169
}
165170

166-
## Handle if some elements are 'NA'
167-
if (any(is.na(d[, 1:2]))) {
168-
warning("In `d' `NA' elements were replaced with string \"NA\"")
169-
d[, 1:2][is.na(d[, 1:2])] <- "NA"
170-
}
171-
if (!is.null(vertices) && any(is.na(vertices[, 1]))) {
172-
warning("In `vertices[,1]' `NA' elements were replaced with string \"NA\"")
173-
vertices[, 1][is.na(vertices[, 1])] <- "NA"
171+
if (!is.null(vertices) && ncol(vertices) >= 1) {
172+
names <- vertices$name
173+
if (!is.null(names)) {
174+
if (anyNA(names)) {
175+
warning('Replacing `NA` in vertex names in `vertices` with the string "NA"')
176+
names[is.na(names)] <- "NA"
177+
}
178+
if (anyDuplicated(names)) {
179+
stop("Duplicate vertex names")
180+
}
181+
}
182+
} else {
183+
names <- NULL
174184
}
175185

176-
names <- unique(c(as.character(d[, 1]), as.character(d[, 2])))
177-
if (!is.null(vertices)) {
178-
names2 <- names
179-
vertices <- as.data.frame(vertices)
180-
if (ncol(vertices) < 1) {
181-
stop("Vertex data frame contains no rows")
186+
if (is.numeric(d[[1]]) && !is.factor(d[[1]]) && is.numeric(d[[2]]) && !is.factor(d[[2]])) {
187+
edges <- rbind(d[[1]], d[[2]])
188+
names <- seq_len(max(edges, 0L))
189+
} else {
190+
if (is.null(names)) {
191+
names <- unique(c(as.character(d[[1]]), as.character(d[[2]])))
192+
}
193+
194+
if (!("name" %in% names(vertices))) {
195+
vertices <- cbind(data.frame(name = names), vertices)
182196
}
183-
names <- as.character(vertices[, 1])
184-
if (any(duplicated(names))) {
185-
stop("Duplicate vertex names")
197+
198+
name_edges <- rbind(as.character(d[[1]]), as.character(d[[2]]))
199+
200+
if (anyNA(name_edges)) {
201+
warning('Replacing `NA` in vertex names in `d` with the string "NA"')
202+
name_edges[is.na(name_edges)] <- "NA"
186203
}
187-
if (any(!names2 %in% names)) {
188-
stop("Some vertex names in edge list are not listed in vertex data frame")
204+
205+
edges <- matrix(match(name_edges, names), nrow = 2)
206+
if (anyNA(edges)) {
207+
stop(
208+
"Vertex name ",
209+
name_edges[is.na(edges)][[1]],
210+
" in edge list is not listed in vertex data frame"
211+
)
189212
}
190213
}
191214

192215
# create graph
193216
g <- make_empty_graph(n = 0, directed = directed)
194217

195218
# vertex attributes
196-
attrs <- list(name = names)
197-
if (!is.null(vertices)) {
198-
if (ncol(vertices) > 1) {
199-
for (i in 2:ncol(vertices)) {
200-
newval <- vertices[, i]
201-
if (inherits(newval, "factor")) {
202-
newval <- as.character(newval)
203-
}
204-
attrs[[names(vertices)[i]]] <- newval
205-
}
206-
}
207-
}
219+
vattrs <- lapply(vertices, unfactor)
208220

209221
# add vertices
210-
g <- add_vertices(g, length(names), attr = attrs)
211-
212-
# create edge list
213-
from <- as.character(d[, 1])
214-
to <- as.character(d[, 2])
215-
edges <- rbind(match(from, names), match(to, names))
222+
g <- add_vertices(g, length(names), attr = vattrs)
216223

217224
# edge attributes
218-
attrs <- list()
219-
if (ncol(d) > 2) {
220-
for (i in 3:ncol(d)) {
221-
newval <- d[, i]
222-
if (inherits(newval, "factor")) {
223-
newval <- as.character(newval)
224-
}
225-
attrs[[names(d)[i]]] <- newval
226-
}
227-
}
225+
eattrs <- lapply(d[-1:-2], unfactor)
228226

229227
# add the edges
230-
g <- add_edges(g, edges, attr = attrs)
228+
g <- add_edges(g, edges, attr = eattrs)
229+
231230
g
232231
}
233232

233+
unfactor <- function(x) {
234+
if (!inherits(x, "factor")) {
235+
return(x)
236+
}
237+
238+
as.character(x)
239+
}
240+
234241
#' @rdname graph_from_data_frame
235242
#' @param ... Passed to `graph_from_data_frame()`.
236243
#' @export

man/graph_from_data_frame.Rd

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)