Nothing
#' Add nodes and attributes to graph from a table
#'
#' @description
#'
#' Add nodes and their attributes to an existing graph object from data in a CSV
#' file or a data frame.
#'
#' @inheritParams render_graph
#' @param table Either a path to a CSV file, or, a data frame object.
#' @param label_col An option to apply a column of data in the table as `label`
#' attribute values.
#' @param type_col An option to apply a column of data in the table as `type`
#' attribute values.
#' @param set_type An optional string to apply a `type` attribute to all nodes
#' created from data in the external table.
#' @param drop_cols An optional column selection statement for dropping columns
#' from the external table before inclusion as attributes in the graph's
#' internal node data frame. Several columns can be dropped by name using the
#' syntax `col_1 & col_2 & ...`. Columns can also be dropped using a numeric
#' column range with `:` (e.g., `5:8`), or, by using the `:` between column
#' names to specify the range (e.g., `col_5_name:col_8_name`).
#'
#' @return A graph object of class `dgr_graph`.
#'
#' @examples
#' # To add nodes from the dataset called
#' # `currencies` (available as a dataset
#' # in the package), call the
#' # `add_nodes_from_table()` function
#' # after creating an empty graph; new
#' # node ID values will be created as
#' # monotonically-increasing values
#' graph_1 <-
#' create_graph() %>%
#' add_nodes_from_table(
#' table = currencies)
#'
#' # View part of the graph's internal
#' # node data frame (ndf)
#' graph_1 %>%
#' get_node_df() %>%
#' .[, 1:5] %>%
#' head()
#'
#' # If you would like to assign
#' # any of the table's columns as
#' # `type` or `label` attributes,
#' # this can be done with the `type_col`
#' # and `label_col` arguments; to set
#' # a static `type` attribute for all
#' # of the table records, use `set_type`
#' graph_2 <-
#' create_graph() %>%
#' add_nodes_from_table(
#' table = currencies,
#' label_col = iso_4217_code,
#' set_type = currency)
#'
#' # View part of the graph's internal ndf
#' graph_2 %>%
#' get_node_df() %>%
#' .[, 1:5] %>%
#' head()
#'
#' # Suppose we would like to not
#' # include certain columns from the
#' # external table in the resulting
#' # graph; we can use the `drop_cols`
#' # argument to choose which columns
#' # to not include as attributes
#' graph_3 <-
#' create_graph() %>%
#' add_nodes_from_table(
#' table = currencies,
#' label_col = iso_4217_code,
#' set_type = currency,
#' drop_cols = exponent & currency_name)
#'
#' # Show the node attribute names
#' # for the graph; note that the
#' # `exponent` and `currency_name`
#' # columns are not attributes in the
#' # graph's internal node data frame
#' graph_3 %>%
#' get_node_df() %>%
#' colnames()
#'
#' @family node creation and removal
#'
#' @export
add_nodes_from_table <- function(
graph,
table,
label_col = NULL,
type_col = NULL,
set_type = NULL,
drop_cols = NULL
) {
# Get the time of function start
time_function_start <- Sys.time()
# Validation: Graph object is valid
check_graph_valid(graph)
# TODO use new technique to convert to string.
# Get the requested `label_col`
label_col <-
rlang::enquo(label_col) %>% rlang::get_expr() %>% as.character()
# Get the requested `type_col`
type_col <-
rlang::enquo(type_col) %>% rlang::get_expr() %>% as.character()
# Get the requested `set_type`
set_type <-
rlang::enquo(set_type) %>% rlang::get_expr() %>% as.character()
# Get the requested `drop_cols`
drop_cols <-
rlang::enquo(drop_cols) %>% rlang::get_expr() %>% as.character()
if (length(label_col) == 0) {
label_col <- NULL
}
if (length(type_col) == 0) {
type_col <- NULL
}
if (length(set_type) == 0) {
set_type <- NULL
}
if (length(drop_cols) == 0) {
drop_cols <- NULL
} else {
drop_cols <- drop_cols[drop_cols != "&"]
drop_cols <- paste(drop_cols, collapse = " & ")
}
# Get the number of nodes ever created for
# this graph
nodes_created <- graph$last_node
if (inherits(table, "character")) {
# Load in CSV file
csv <- utils::read.csv(table, stringsAsFactors = FALSE)
} else if (inherits(table, "data.frame")) {
# Rename `table` object as `csv`
csv <- as.data.frame(table, stringsAsFactors = FALSE)
}
# Get number of rows in the CSV
rows_in_csv <- nrow(csv)
# Create an empty ndf and bind those columns
# with the table data
ndf <- create_node_df(n = rows_in_csv)
# Optionally set the `label` attribute from a
# specified column in the CSV (this copies data into
# the `label` column)
if (!is.null(label_col)) {
colnames(csv)[which(colnames(csv) == label_col)] <- "label"
ndf$label <- as.character(csv[, which(colnames(csv) == "label")])
}
# Optionally set the `type` attribute from a
# specified column in the CSV (this copies data into
# the `type` column)
if (!is.null(type_col)) {
colnames(csv)[which(colnames(csv) == type_col)] <- "type"
ndf$type <- as.character(csv[, which(colnames(csv) == "type")])
}
# If an `id` column exists in the external
# table, copy those values in as `id_external`
if ("id" %in% colnames(csv)) {
colnames(csv)[which(colnames(csv) == "id")] <- "id_external"
ndf$id_external <- csv$id_external
}
# Optionally set the `type` attribute with a single
# value repeated down
if (is.null(type_col) && !is.null(set_type)) {
ndf$type <- as.character(set_type)
}
# Get the remaining columns from `csv`
# to add to the ndf
columns_to_add <-
base::setdiff(colnames(csv), colnames(ndf))
# If values for `drop_cols` provided,
# further filter the list of column data
# to migrate to `ndf`
if (!is.null(drop_cols)) {
col_selection <- get_col_selection(col_selection_stmt = drop_cols)
if (col_selection[["selection_type"]] == "column_range") {
col_index_1 <- which(colnames(csv) == col_selection[["column_selection"]][1])
col_index_2 <- which(colnames(csv) == col_selection[["column_selection"]][2])
col_indices <- col_index_1:col_index_2 %>% sort()
columns_to_add <- base::setdiff(columns_to_add, colnames(csv)[col_indices])
} else if (col_selection[["selection_type"]] == "column_index_range") {
col_indices <- col_selection[["column_selection"]] %>% sort()
columns_to_add <- base::setdiff(columns_to_add, colnames(csv)[col_indices])
} else if (col_selection[["selection_type"]] %in% c("single_column_name", "column_names")) {
columns_to_add <- base::setdiff(columns_to_add, col_selection[["column_selection"]])
} else if (length(col_selection) == 0) {
columns_to_add <- columns_to_add
}
}
# Move any additional columns from the
# external table to `ndf`
ndf <-
dplyr::bind_cols(
ndf,
dplyr::select(csv, dplyr::all_of(columns_to_add))
)
# Get the number of nodes in the graph
nodes_graph_1 <- graph %>% count_nodes()
# Add node data frame `ndf` to the graph
graph <- add_node_df(graph, ndf)
# Redact the signing of the action to the log
graph$graph_log <-
graph$graph_log[-nrow(graph$graph_log), ]
# Get the updated number of nodes in the graph
nodes_graph_2 <- graph %>% count_nodes()
# Get the number of nodes added to
# the graph
nodes_added <- nodes_graph_2 - nodes_graph_1
# Update the `last_node` counter
graph$last_node <- nodes_created + nodes_added
# Get the name of the function
fcn_name <- get_calling_fcn()
# Update the `graph_log` df with an action
graph$graph_log <-
add_action_to_log(
graph_log = graph$graph_log,
version_id = nrow(graph$graph_log) + 1L,
function_used = fcn_name,
time_modified = time_function_start,
duration = graph_function_duration(time_function_start),
nodes = nrow(graph$nodes_df),
edges = nrow(graph$edges_df),
d_n = nodes_added)
# Perform graph actions, if any are available
if (nrow(graph$graph_actions) > 0) {
graph <-
graph %>%
trigger_graph_actions()
}
# Write graph backup if the option is set
if (graph$graph_info$write_backups) {
save_graph_as_rds(graph = graph)
}
graph
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.