"""
# INTRODUCTION

Based on the books of George R.R. Martin, the HBO serie GAME OF THRONES has released different seasons with different characters. Some of them dies, some of them survive, but the importance of each of them change according to the moment of the story. 

In this project **we will analyze the co-occurence network of the characters**. This analysis is based on the books. 

<font color="#008000">Co-occurence : </font> 2 characters are considered to co-occur if their names appear in the surrounding of 15 words from one another. 
"""
"""
# I - Import of the environment
"""
"""
Let's start with book 1
"""
# Importing modules
import pandas as pd

# Reading in datasets/book1.csv
book1 = pd.read_csv("/kaggle/input/gameofthrones-book1/book1.csv")
book2 = pd.read_csv("/kaggle/input/gameofthrones-book2/book2.csv")
book3 = pd.read_csv("/kaggle/input/gameofthrones-book3/book3.csv")
book4 = pd.read_csv("/kaggle/input/gameofthrones-book4/book4.csv")
book5 = pd.read_csv("/kaggle/input/gameofthrones-book5/book5.csv")


# Printing out the head of the dataset - example of book 1
book1.head()
"""
We have 5 columns. 

We have 2 nodes that are linked by an edge : Source & target. 

A network can have directed or undirected edges and in this network all the edges are undirected. The weight attribute of every edge tells us the number of interactions that the characters have had over the book, and the book column tells us the book number.
"""
"""
> We are going to use : https://networkx.org/documentation/networkx-2.0/reference/classes/index.html
        
> NetworkX provides data structures and methods for storing graphs.

> All NetworkX graph classes allow (hashable) Python objects as nodes and any Python object can be assigned as an edge attribute.
"""
# Importing modules
import networkx as nx

# Creating an empty graph object
G_book1 = nx.Graph()
"""
Currently, the graph object G_book1 is empty. Let's now populate it with the edges from book1. And while we're at it, let's load in the rest of the books too!
"""
# Iterating through the DataFrame to add edges
for _, edge in book1.iterrows():
    G_book1.add_edge(edge['Source'], edge['Target'], weight=edge['weight'])

# Creating a list of networks for all the books
books = [G_book1]
book_fnames = ['../input/gameofthrones-book2/book2.csv', '../input/gameofthrones-book3/book3.csv', '../input/gameofthrones-book4/book4.csv', '../input/gameofthrones-book5/book5.csv']
for book_fname in book_fnames:
    book = pd.read_csv(book_fname)
    G_book = nx.Graph()
    for _, edge in book.iterrows():
        G_book.add_edge(edge['Source'], edge['Target'], weight=edge['weight'])
    books.append(G_book)
"""
# Network & node : which character is the most important ?
"""
"""
First, let's measure the importance of a node in a network by looking at the number of neighbors it has, that is, the number of nodes it is connected to. **This measure of importance is called degree centrality.**
"""
"""


Centrality Measures allows us to pinpoint the most important nodes of a Graph. This essentially helps us to identify :

- Influential nodes in a Social Network.
- Nodes that disseminate information to many nodes
- Hubs in a transportation network
- Important pages in the Web
- Nodes that prevent the Network from breaking up

**This is based on the assumption that important nodes have many connections.**




https://www.geeksforgeeks.org/network-centrality-measures-in-a-graph-using-networkx-python/


https://coderzcolumn.com/tutorials/data-science/network-analysis-in-python-node-importance-and-paths-networkx
"""
#Using this measure, let's extract the top ten important characters from the first book (book[0]) and the fifth book (book[4]).

# Calculating the degree centrality of book 1
deg_cen_book1 = nx.degree_centrality(books[0])

# Calculating the degree centrality of book 5
deg_cen_book5 = nx.degree_centrality(books[4])

# Sorting the dictionaries according to their degree centrality and extracting the top 10
sorted_deg_cen_book1 = sorted(deg_cen_book1.items(), key=lambda x:x[1], reverse=True)[0:10]

# Sorting the dictionaries according to their degree centrality and extracting the top 10
sorted_deg_cen_book5 = sorted(deg_cen_book5.items(), key=lambda x:x[1], reverse=True)[0:10]

# Printing out the top 10 of book1 and book5
print("Book 1", sorted_deg_cen_book1)
print("and")
print("Book 5", sorted_deg_cen_book5)
"""
# Evolution of importance throught the books
"""
"""
According to degree centrality, the most important character in the first book is Eddard Stark but he is not even in the top 10 of the fifth book. The importance of characters changes over the course of five books. 
The high "death-activity" might be one of the explaination.
"""
"""
Let's look at the evolution of degree centrality of a couple of characters like Eddard Stark, Jon Snow, and Tyrion, which showed up in the top 10 of degree centrality in the first book.
"""
%matplotlib inline
import matplotlib.pyplot as plt

# Creating a list of degree centrality of all the books
evol = [nx.degree_centrality(book) for book in books]
 
# Creating a DataFrame from the list of degree centralities in all the books
degree_evol_df = pd.DataFrame.from_records(evol)

# Plotting the degree centrality evolution of Eddard-Stark, Tyrion-Lannister and Jon-Snow
degree_evol_df[['Eddard-Stark', 'Tyrion-Lannister', 'Jon-Snow']].plot();

          
plt.xlabel("Books number", size = 16,)
plt.ylabel("importance", size = 16)

plt.title("Evolution of character s importance through the five books", 
          fontdict={'family': 'serif', 
                    'color' : 'darkblue',
                    'weight': 'bold',
                    'size': 16},
          loc='left')

"""
**conclusions** We can see that the importance of Eddard Stark dies off as the book series progresses. With Jon Snow, there is a drop in the fourth book but a sudden rise in the fifth book.

"""
"""
# betweenness centrality and PageRank
"""
# Creating a list of betweenness centrality of all the books just like we did for degree centrality
evol = [nx.betweenness_centrality(book, weight='weight') for book in books]

# Making a DataFrame from the list
betweenness_evol_df = pd.DataFrame.from_records(evol).fillna(0)

# Finding the top 4 characters in every book
set_of_char = set()
for i in range(5):
    set_of_char |= set(list(betweenness_evol_df.T[i].sort_values(ascending=False)[0:4].index))
list_of_char = list(set_of_char)

# Plotting the evolution of the top characters
betweenness_evol_df[list_of_char].plot(figsize=(13, 7))
"""
# Google PageRank
"""
"""
PageRank was the initial way Google ranked web pages. It evaluates the inlinks and outlinks of webpages in the world wide web, which is, essentially, a directed network. Let's look at the importance of characters in the Game of Thrones network according to PageRank.
"""
# Creating a list of pagerank of all the characters in all the books
evol = [nx.pagerank(book) for book in books]

# Making a DataFrame from the list
pagerank_evol_df = pd.DataFrame.from_records(evol).fillna(0)

# Finding the top 4 characters in every book
set_of_char = set()
for i in range(5):
    set_of_char |= set(list(pagerank_evol_df.T[i].sort_values(ascending=False)[0:4].index))
list_of_char = list(set_of_char)

# Plotting the top characters
pagerank_evol_df[list_of_char].plot(figsize=(13, 7))
"""
# Correlation between different measures
"""
"""
Stannis, Jon Snow, and Daenerys are the most important characters in the fifth book according to PageRank. Eddard Stark follows a similar curve but for degree centrality and betweenness centrality: He is important in the first book but dies into oblivion over the book series.

We have seen three different measures to calculate the importance of a node in a network, and all of them tells us something about the characters and their importance in the co-occurrence network. We see some names pop up in all three measures so maybe there is a strong correlation between them?

Let's look at the correlation between PageRank, betweenness centrality and degree centrality for the fifth book using Pearson correlation.
"""
# Creating a list of pagerank, betweenness centrality, degree centrality
# of all the characters in the fifth book.
measures = [nx.pagerank(books[4]), 
            nx.betweenness_centrality(books[4], weight='weight'), 
            nx.degree_centrality(books[4])]

# Creating the correlation DataFrame
cor = pd.DataFrame.from_records(measures)

# Calculating the correlation
cor.T.corr()
"""
# Conclusion

We see a high correlation between these three measures for our character co-occurrence network.

So we've been looking at different ways to find the important characters in the Game of Thrones co-occurrence network. According to degree centrality, Eddard Stark is the most important character initially in the books. But who is/are the most important character(s) in the fifth book according to these three measures?
"""
# Finding the most important character in the fifth book,
# according to degree centrality, betweenness centrality and pagerank.
p_rank, b_cent, d_cent = cor.idxmax(axis=1)

# Printing out the top character accoding to the three measures
print(p_rank)
print(b_cent)
print(d_cent)
"""
COMMENTS : 
    
    Check these additional website : https://github.com/harrisonpim/bookworm
    https://networkofthrones.wordpress.com/the-novels/
    https://networkofthrones.wordpress.com/
"""