@@ -100,16 +100,17 @@ graph.data.frame <- function(d, directed = TRUE, vertices = NULL) { # nocov star
100
100
# ' is returned, in a list with named entries `vertices` and `edges`.
101
101
# '
102
102
# ' @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
104
105
# ' version 0.7 this argument is coerced to a data frame with
105
- # ' ` as.data.frame` .
106
+ # ' [ as.data.frame()] .
106
107
# ' @param directed Logical scalar, whether or not to create a directed graph.
107
108
# ' @param vertices A data frame with vertex metadata, or `NULL`. See
108
109
# ' 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`.
110
111
# ' @return An igraph graph object for `graph_from_data_frame()`, and either a
111
112
# ' data frame or a list of two data frames named `edges` and
112
- # ' `vertices` for ` as.data.frame` .
113
+ # ' `vertices` for [ as.data.frame()] .
113
114
# ' @note For `graph_from_data_frame()` `NA` elements in the first two
114
115
# ' columns \sQuote{d} are replaced by the string \dQuote{NA} before creating
115
116
# ' the graph. This means that all `NA`s will correspond to a single
@@ -155,82 +156,90 @@ graph.data.frame <- function(d, directed = TRUE, vertices = NULL) { # nocov star
155
156
# ' @export
156
157
graph_from_data_frame <- function (d , directed = TRUE , vertices = NULL ) {
157
158
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 )) {
159
162
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" )
160
165
}
161
166
162
167
if (ncol(d ) < 2 ) {
163
- stop(" the data frame should contain at least two columns" )
168
+ stop(" `d` should contain at least two columns" )
164
169
}
165
170
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
174
184
}
175
185
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 (is.null(vertices )) {
195
+ vertices <- data.frame (name = names )
196
+ } else if (! (" name" %in% names(vertices ))) {
197
+ vertices <- cbind(data.frame (name = names ), vertices )
182
198
}
183
- names <- as.character(vertices [, 1 ])
184
- if (any(duplicated(names ))) {
185
- stop(" Duplicate vertex names" )
199
+
200
+ name_edges <- rbind(as.character(d [[1 ]]), as.character(d [[2 ]]))
201
+
202
+ if (anyNA(name_edges )) {
203
+ warning(' Replacing `NA` in vertex names in `d` with the string "NA"' )
204
+ name_edges [is.na(name_edges )] <- " NA"
186
205
}
187
- if (any(! names2 %in% names )) {
188
- stop(" Some vertex names in edge list are not listed in vertex data frame" )
206
+
207
+ edges <- matrix (match(name_edges , names ), nrow = 2 )
208
+ if (anyNA(edges )) {
209
+ stop(
210
+ " Vertex name " ,
211
+ name_edges [is.na(edges )][[1 ]],
212
+ " in edge list is not listed in vertex data frame"
213
+ )
189
214
}
190
215
}
191
216
192
217
# create graph
193
218
g <- make_empty_graph(n = 0 , directed = directed )
194
219
195
220
# 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
- }
221
+ vattrs <- lapply(vertices , unfactor )
208
222
209
223
# 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 ))
224
+ g <- add_vertices(g , length(names ), attr = vattrs )
216
225
217
226
# 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
- }
227
+ eattrs <- lapply(d [- 1 : - 2 ], unfactor )
228
228
229
229
# add the edges
230
- g <- add_edges(g , edges , attr = attrs )
230
+ g <- add_edges(g , edges , attr = eattrs )
231
+
231
232
g
232
233
}
233
234
235
+ unfactor <- function (x ) {
236
+ if (! inherits(x , " factor" )) {
237
+ return (x )
238
+ }
239
+
240
+ as.character(x )
241
+ }
242
+
234
243
# ' @rdname graph_from_data_frame
235
244
# ' @param ... Passed to `graph_from_data_frame()`.
236
245
# ' @export
0 commit comments