<jupyter_start><jupyter_text>Importing the Data<jupyter_code>import pickle
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import numpy as np

with open('interactions.pickle', 'rb') as handle:
    my_dict = pickle.load(handle)<jupyter_output><empty_output><jupyter_text>Functionality 1 - Get the overall features of the graphIt takes in input:* One of the 3 graphsThe output should return:* Whether the graph is directed or not* Number of users* Number of answers/comments* Average number of links per user* Density degree of the graph* Whether the graph is sparse or dense  1.1 Graph is directed or not?<jupyter_code>def directed_or_undirected_f(dict_to_search):
    '''
    If a vertex u has a edge that goes to vertex v, and v doesn't have a vertex that goes back to u, then the graph is directed. 
    We will prove this by checking the keys of our dictionary until we find the descripted situation. 
    '''
    is_directed = True # Suppose graph is directed until proven the contrary
    
    for each_key in dict_to_search.keys(): #for each key of the dictionary
        
        target_nodes = set(np.array(dict_to_search[each_key])[:,0])
        for each_adjacent_node in target_nodes:
            if(each_adjacent_node not in dict_to_search.keys()): #If the adjacent node is not in keys, then there's not edge going back
                is_directed = False
                return(is_directed)
            
            adjacent_nodes = set(np.array(dict_to_search[each_adjacent_node])[:,0])
            
            if(each_key not in adjacent_nodes):
                is_directed = False
                return(is_directed)
    return(is_directed)
def density_distri_plot(graph_to_analyze):
    '''
    Function to count the frequency of the number of outgoing edges in each key of the graph to then plot the degree distribution. 
    '''
    keys = dict_test_2.keys()
    list_density = []
    for each_key in keys:
        list_density.append(len(dict_test_2[each_key]))
    return list_density<jupyter_output><empty_output><jupyter_text>1.2 Number of usersWe will implement **Depth First Search (DFS)** to count the number of users that the graph has.<jupyter_code>def number_of_users_f(dict_to_search):
    
    dict_keys = set(dict_to_search.keys())
    total_users = dict_keys
    
    for each_key in dict_keys.copy():
        target_nodes = set(np.array(dict_to_search[each_key])[:,0])
        difference = target_nodes.difference(total_users)
        total_users.update(difference)
    
    return(len(total_users))<jupyter_output><empty_output><jupyter_text>1.3 Number of answers/comments  1.4 Average number of links per user<jupyter_code>def outgoing_edges_f(dict_to_search):
    '''
    Function computes the total number of edges that exit from all the keys of the dictionary
    '''
    num_outgoing_edges = 0
    
    for each_key in dict_to_search.keys(): #Takes each key of the dictionary
        outgoing_edges = np.array(dict_to_search[each_key])[:,0] #Takes each target node for a particular source node
        num_outgoing_edges += len(outgoing_edges) #Increases the total number of outgoing edges by the total target nodes for a particular source node
    
    return(num_outgoing_edges)
def avg_num_links_f(num_of_users,num_of_edges):
    '''
    Function compues the average number of links per user by dividing the total number of edges of the dictionaty by the total number of users
    '''
    #num_outgoing_edges = outgoing_edges_f(dict_to_search)
    
    average_num_links = num_of_edges/num_of_users
    
    return(average_num_links)<jupyter_output><empty_output><jupyter_text>1.5 Density degree of the graph<jupyter_code>def graph_density_f(edges_num, vertexes_num):
    return(edges_num/(vertexes_num*(vertexes_num-1))/2)<jupyter_output><empty_output><jupyter_text>1.6 Whether the graph is sparse or dense<jupyter_code>def sparse_or_dense_f(density_degree,threshold):
    if density_degree >= threshold:
        sparsity_result = "Is dense with a threshold of "+str(threshold)+"!"
    else:
        sparsity_result = "Is sparse with a threshold of "+str(threshold)+"!"
    return sparsity_result
def functionality_1(dict_to_search):
    number_vertexes = number_of_users_f(dict_to_search)
    number_edges = outgoing_edges_f(dict_to_search)
    graph_density = graph_density_f(number_edges,number_vertexes)
    directed_or_undirected = ("The graph is undirected") if directed_or_undirected_f(dict_to_search) else ("The graph is directed")
    list_density = density_distri_plot(dict_to_search)
    output_f1 = {'Info': ['Graph is directed or undirected?', 'Total number of users', 'Total number of answers/comments', 
                 'Average number of links per user','Graph Density Degree','Graph is sparse or dense?'],
                 'Result': [directed_or_undirected,number_vertexes,'NA',avg_num_links_f(number_vertexes,number_edges),
                           graph_density,sparse_or_dense_f(graph_density,0.1)]}
    output_f1 = pd.DataFrame(output_f1)
    
    
    #Visualization
    %matplotlib inline

    plt.hist(list_density, bins=20) 
    plt.ylabel('Graph Density')
    plt.title(label = 'Density distribution of Merged graph')
    
    return output_f1
functionality_1(my_dict)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.07744616547034379, 'fraction_numerical': 0.006233471854930109, 'mean_word_length': 3.925581395348837, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 26, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '178213', 'license': 'MIT', 'n_tokens_mistral': 1652, 'n_tokens_neox': 1600, 'n_words': 465, 'path': 'Functionality_1/Functionality_1.ipynb', 'repo_name': 'brauliovillalobos/ADM_HW5', 'size': '5294'}