This representation assumes that vertices and edges are encoded in
    two lists, each list containing a Python dict for each vertex and
    each edge, respectively. A distinguished element of the vertex dicts
    contain a vertex ID which is used in the edge dicts to refer to
    source and target vertices. All the remaining elements of the dicts
    are considered vertex and edge attributes.

    @param vertices: a list of dicts for the vertices.
    @param edges: a list of dicts for the edges.
    @param vertex_name_key: the name of the distinguished key in the dicts
      in the vertex data source that contains the vertex names. Will also be used
      as vertex label.
    @param vertex_id_key: the name of the distinguished key in the dicts
      in the vertex data source that contains a unique identifier for the vertex.
    @param edge_foreign_keys: the name of the attributes in the dicts in C{edges}
      that contain the source and target vertex names.
    @return: IGraph instance with integers for vertex ids, edge sources, and edge targets.

def from_vertices_and_edges(vertices, edges, vertex_name_key='name', vertex_id_key='id',
                            edge_foreign_keys=('source', 'target'), directed=True):
    """
    This representation assumes that vertices and edges are encoded in
    two lists, each list containing a Python dict for each vertex and
    each edge, respectively. A distinguished element of the vertex dicts
    contain a vertex ID which is used in the edge dicts to refer to
    source and target vertices. All the remaining elements of the dicts
    are considered vertex and edge attributes.

    @param vertices: a list of dicts for the vertices.
    @param edges: a list of dicts for the edges.
    @param vertex_name_key: the name of the distinguished key in the dicts
      in the vertex data source that contains the vertex names. Will also be used
      as vertex label.
    @param vertex_id_key: the name of the distinguished key in the dicts
      in the vertex data source that contains a unique identifier for the vertex.
    @param edge_foreign_keys: the name of the attributes in the dicts in C{edges}
      that contain the source and target vertex names.
    @return: IGraph instance with integers for vertex ids, edge sources, and edge targets.
    """
    vertex_data = _dicts_to_columns(vertices)
    edge_data = _dicts_to_columns(edges)
    n = len(vertices)
    vertex_index = dict(zip(vertex_data[vertex_id_key], range(n)))

    # Iterate over `edges` to create `edge_list`, where every list item is a pair of integers.
    edge_list = list(map(lambda source, target: (vertex_index[source], vertex_index[target]),
                         edge_data[edge_foreign_keys[0]],
                         edge_data[edge_foreign_keys[1]]))

    g = IGraph(n=n, edges=edge_list, directed=directed, vertex_attrs=vertex_data, edge_attrs=edge_data)
    g.vs['name'] = g.vs[vertex_name_key]
    g.vs['indegree'] = g.degree(mode="in")
    g.vs['outdegree'] = g.degree(mode="out")
    g.vs['label'] = g.vs[vertex_name_key]
    if 'group' not in g.vs.attributes():
        g.vs['group'] = labels_to_groups(g.vs['label'])
    return g