<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Project_2
Step1:  Reading the text file into the Ipython Notebook
Step2:  First i want to seperate the lines so i will strip them, and store them in a list using a list comprehension.
Step3:  Print out the list, to inspect how it's formated and changes that will need to be made. (Cleaning)
Step4:  I want to split up what's easy for me to take from the list, so i've created a few lists to store those in.
Step5:  Using Regex to clean some of the data inside the table before we loop through it, so it can be easier to accesss the desired information from the table list we've created.
Step6:  Using a for-loop to parse through the table, i've split the rows seperately becaues they are formated differently, making it easier to work once on each unique row set.
Step7:  Because i still need to process more information and because some cells are misformed with extra data, i need to run another forloop to reach a more detailed cleaning, I am also going to create some list of columns to store these values.
Step8:  I want to set the max number of rows to 70 for DataFrames because there are a total of 64 I.D. and if there are more than set ammount it can be a sign that i've made a mistake.
Step9:  I will de doing the same with the alternate rows and cleaning it in the process.
Step10:  Here I want to add the columns that the DataFrame needs so i do index and list comprehension for each particular one.
Step11:  The following is the use of indexing and mapping of cells containting letters and the process of removing them using map function and lambdas.
Step12:  I want to replace the empty string values with get.nan but because further along this notebook, i was presented with a ValueError i've returned and set them to 0. (Not sure if this is going to affect the data much), although some rows contain a number of unplayed games, and it may contribute to some difference in players with unplayed matches.
Step13:  Printing the DataFrame constantly throughout helps to visualize the changes and not make unnecessary changes to the object.
Step14:  I have indexed to the Player Names to compare the data better to the original table.
Step15:  Below I've creating a series of the data i wish to analyze further and do computational processes on.
Step16:  Here I wanted to create a function that would loop through the data and return the desired result.
This function is indexing the cells in the columns to their respective indexed players rating and replacing them, after this replacement is made all the data is then computed and divided by the number of games played which returns a column with the players Average Pre Tournament Chess Rating of Opponents.
Step17:  Creating an object that will process the parse_series function and return its list values.
Step18:  Adding the column -Average_Rating- to the games_df DataFrame object.
Step19:  As we can see, the Average Ratings have been computed and now applied to the original DataFrame Object, here is the top 5 rows.
Step20:  Here are te last 5 rows in the DataFrame object.
Step21:  Now since all computations are done, and the data that we want is in the DataFrame, we can create and send to CSV File using the to_csv method.
<ASSISTANT_TASK:>
Python Code:
import pandas as pd
import re
import sys
import numpy as np
Explanation: Project_2: Read Chess Tournament Cross Table
End of explanation
textfile = open('tournamentinfo.txt')
Explanation: Reading the text file into the Ipython Notebook
End of explanation
text_table = [line.strip() for line in textfile.readlines()]
Explanation: First i want to seperate the lines so i will strip them, and store them in a list using a list comprehension.
End of explanation
text_table
Explanation: Print out the list, to inspect how it's formated and changes that will need to be made. (Cleaning)
End of explanation
player_state = []
player_number = []
id_data = []
name_data = []
Explanation: I want to split up what's easy for me to take from the list, so i've created a few lists to store those in.
End of explanation
state = '([A-Z]{2})'
number = '([0-9]{1})'
dash = '^-'
Explanation: Using Regex to clean some of the data inside the table before we loop through it, so it can be easier to accesss the desired information from the table list we've created.
End of explanation
for line in text_table:
    if not re.search(dash, line):
        if re.search(state, line) and not re.search(dash, line):
            text =  line.replace('/', '').replace('-','').replace('>','').replace(':','') 
            state_num = text.strip().replace('|', ',')[:3].strip(',')
            if re.search(state, state_num):
                player_state.append(state_num)
                id_data.append(text[5:].strip('').replace('|',','))
            elif re.search(number, state_num):
                name_data.append(text[4:].strip().replace('|',','))
                player_number.append(state_num)
Explanation: Using a for-loop to parse through the table, i've split the rows seperately becaues they are formated differently, making it easier to work once on each unique row set.
End of explanation
player_names = []
rounds = []
uscf_id = []
ratings = []
total_points = []
for item in name_data:
    total_points.append(float(item[33:36]))
    player_names.append(item[:28].split())
    rounds.append(item[39:].replace(' ', '' ).strip(',').split(','))
Explanation: Because i still need to process more information and because some cells are misformed with extra data, i need to run another forloop to reach a more detailed cleaning, I am also going to create some list of columns to store these values.
End of explanation
pd.options.display.max_rows = 70
games_df = pd.DataFrame(rounds, columns = ['Round1','Round2','Round3','Round4','Round5','Round6','Round7'], 
                   index = [player for player in player_number])
Explanation: I want to set the max number of rows to 70 for DataFrames because there are a total of 64 I.D. and if there are more than set ammount it can be a sign that i've made a mistake.
End of explanation
for item in id_data:
    uscf_id.append(item.replace('R', '').replace('P', ' ')[:8])
    ratings.append(item.replace('R', '').replace('P', ' ')[11:16])
Explanation: I will de doing the same with the alternate rows and cleaning it in the process.
End of explanation
games_df['Ratings'] = [rate for rate in ratings]
games_df['Total_Points'] = [n for n in total_points]
games_df['Player_ID'] = [n for n in player_number]
games_df['State'] = [state for state in player_state]
games_df['Player_Names'] = [player for player in player_names]
Explanation: Here I want to add the columns that the DataFrame needs so i do index and list comprehension for each particular one.
End of explanation
games_df['Round1'] = games_df['Round1'].map(lambda x: x.lstrip('W')).map(lambda x: x.lstrip('U'))
games_df['Round1'] = games_df['Round1'].map(lambda x: x.lstrip('D')).map(lambda x: x.lstrip('L'))
games_df['Round1'] = games_df['Round1'].map(lambda x: x.lstrip('H')).map(lambda x: x.lstrip('B'))
games_df['Round1'] = games_df['Round1'].map(lambda x: x.lstrip('X'))
games_df['Round2'] = games_df['Round2'].map(lambda x: x.lstrip('W')).map(lambda x: x.lstrip('U'))
games_df['Round2'] = games_df['Round2'].map(lambda x: x.lstrip('D')).map(lambda x: x.lstrip('L'))
games_df['Round2'] = games_df['Round2'].map(lambda x: x.lstrip('H')).map(lambda x: x.lstrip('B'))
games_df['Round2'] = games_df['Round2'].map(lambda x: x.lstrip('X'))
games_df['Round3'] = games_df['Round3'].map(lambda x: x.lstrip('W')).map(lambda x: x.lstrip('U'))
games_df['Round3'] = games_df['Round3'].map(lambda x: x.lstrip('D')).map(lambda x: x.lstrip('L'))
games_df['Round3'] = games_df['Round3'].map(lambda x: x.lstrip('H')).map(lambda x: x.lstrip('B'))
games_df['Round3'] = games_df['Round3'].map(lambda x: x.lstrip('X'))
games_df['Round4'] = games_df['Round4'].map(lambda x: x.lstrip('W')).map(lambda x: x.lstrip('U'))
games_df['Round4'] = games_df['Round4'].map(lambda x: x.lstrip('D')).map(lambda x: x.lstrip('L'))
games_df['Round4'] = games_df['Round4'].map(lambda x: x.lstrip('H')).map(lambda x: x.lstrip('B'))
games_df['Round4'] = games_df['Round4'].map(lambda x: x.lstrip('X'))
games_df['Round5'] = games_df['Round5'].map(lambda x: x.lstrip('W')).map(lambda x: x.lstrip('U'))
games_df['Round5'] = games_df['Round5'].map(lambda x: x.lstrip('D')).map(lambda x: x.lstrip('L'))
games_df['Round5'] = games_df['Round5'].map(lambda x: x.lstrip('H')).map(lambda x: x.lstrip('B'))
games_df['Round5'] = games_df['Round5'].map(lambda x: x.lstrip('X'))
games_df['Round6'] = games_df['Round6'].map(lambda x: x.lstrip('W')).map(lambda x: x.lstrip('U'))
games_df['Round6'] = games_df['Round6'].map(lambda x: x.lstrip('D')).map(lambda x: x.lstrip('L'))
games_df['Round6'] = games_df['Round6'].map(lambda x: x.lstrip('H')).map(lambda x: x.lstrip('B'))
games_df['Round6'] = games_df['Round6'].map(lambda x: x.lstrip('X'))
games_df['Round7'] = games_df['Round7'].map(lambda x: x.lstrip('W')).map(lambda x: x.lstrip('U'))
games_df['Round7'] = games_df['Round7'].map(lambda x: x.lstrip('D')).map(lambda x: x.lstrip('L'))
games_df['Round7'] = games_df['Round7'].map(lambda x: x.lstrip('H')).map(lambda x: x.lstrip('B'))
games_df['Round7'] = games_df['Round7'].map(lambda x: x.lstrip('X'))
Explanation: The following is the use of indexing and mapping of cells containting letters and the process of removing them using map function and lambdas.
End of explanation
games_df['Round1'].replace('', 0, inplace=True)
games_df['Round2'].replace('', 0, inplace=True)
games_df['Round3'].replace('', 0, inplace=True)
games_df['Round4'].replace('', 0, inplace=True)
games_df['Round5'].replace('', 0, inplace=True)
games_df['Round6'].replace('', 0, inplace=True)
games_df['Round7'].replace('', 0, inplace=True)
Explanation: I want to replace the empty string values with get.nan but because further along this notebook, i was presented with a ValueError i've returned and set them to 0. (Not sure if this is going to affect the data much), although some rows contain a number of unplayed games, and it may contribute to some difference in players with unplayed matches.
End of explanation
games_df
Explanation: Printing the DataFrame constantly throughout helps to visualize the changes and not make unnecessary changes to the object.
End of explanation
games_df.set_index(['Player_Names'])
Explanation: I have indexed to the Player Names to compare the data better to the original table.
End of explanation
games_df.set_index(['Round1', 'Round2', 'Round3', 'Round4', 'Round5', 'Round6', 'Round7'])['Ratings']
Explanation: Below I've creating a series of the data i wish to analyze further and do computational processes on.
End of explanation
def parse_series(series):
    player_mapping = {}
    average_rating = []
    for index, row in series.iterrows():
        player_mapping[int(row['Player_ID'])] = int(row['Ratings'])
    for index, row in series.iterrows():
        
        if row[0] is not None:
            try:
                key1 = int(row.Round1)
                row.Round1 = player_mapping[key1]
                key2 = int(row.Round2)
                row.Round2 = player_mapping[key2]
                key3 = int(row.Round3)
                row.Round3 = player_mapping[key3]
                key4 = int(row.Round4)
                row.Round4 = player_mapping[key4]
                key5 = int(row.Round5)
                row.Round5 = player_mapping[key5]
                key6 = int(row.Round6)
                row.Round6 = player_mapping[key6]
                key7 = int(row.Round7)
                row.Round7 = player_mapping[key7]
                total = row.Round1 + row.Round2 + row.Round3 + row.Round4 + row.Round5 + row.Round6 + row.Round7
                games = len([row.Round1, row.Round2, row.Round3, row.Round4, row.Round5, row.Round6, row.Round7])
                average_rating.append(total/games)
            except KeyError:
                total = int(row.Round1) + int(row.Round2) + int(row.Round3) + int(row.Round4) + int(row.Round5) + int(row.Round6) + int(row.Round7)
                games = len([row.Round1, row.Round2, row.Round3, row.Round4, row.Round5, row.Round6, row.Round7])
                average_rating.append(total/games)
    return average_rating
Explanation: Here I wanted to create a function that would loop through the data and return the desired result.
This function is indexing the cells in the columns to their respective indexed players rating and replacing them, after this replacement is made all the data is then computed and divided by the number of games played which returns a column with the players Average Pre Tournament Chess Rating of Opponents.
End of explanation
average_rate = parse_series(games_df)
Explanation: Creating an object that will process the parse_series function and return its list values.
End of explanation
games_df['Average_Rating'] = [n for n in average_rate]
Explanation: Adding the column -Average_Rating- to the games_df DataFrame object.
End of explanation
games_df.head()
Explanation: As we can see, the Average Ratings have been computed and now applied to the original DataFrame Object, here is the top 5 rows.
End of explanation
games_df.tail()
Explanation: Here are te last 5 rows in the DataFrame object.
End of explanation
games_df.to_csv('Project_2_results', sep=',', encoding='utf-8')
Explanation: Now since all computations are done, and the data that we want is in the DataFrame, we can create and send to CSV File using the to_csv method.
End of explanation
<END_TASK>