# import pandas, but call it pd. Why? Because that's What People Do.
import pandas as pd

"""
Explanation: An Introduction to pandas
Pandas! They are adorable animals. You might think they are the worst animal ever but that is not true. You might sometimes think pandas is the worst library every, and that is only kind of true.
The important thing is use the right tool for the job. pandas is good for some stuff, SQL is good for some stuff, writing raw Python is good for some stuff. You'll figure it out as you go along.
Now let's start coding. Hopefully you did pip install pandas before you started up this notebook.
End of explanation
"""


# We're going to call this df, which means "data frame"
# It isn't in UTF-8 (I saved it from my mac!) so we need to set the encoding
df = pd.read_csv("NBA-Census-10.14.2013.csv", encoding='mac_roman')

"""
Explanation: When you import pandas, you use import pandas as pd. That means instead of typing pandas in your code you'll type pd.
You don't have to, but every other person on the planet will be doing it, so you might as well.
Now we're going to read in a file. Our file is called NBA-Census-10.14.2013.csv because we're sports moguls. pandas can read_ different types of files, so try to figure it out by typing pd.read_ and hitting tab for autocomplete.
End of explanation
"""


# Let's look at all of it
df

"""
Explanation: A dataframe is basically a spreadsheet, except it lives in the world of Python or the statistical programming language R. They can't call it a spreadsheet because then people would think those programmers used Excel, which would make them boring and normal and they'd have to wear a tie every day.
Selecting rows
Now let's look at our data, since that's what data is for
End of explanation
"""


# Look at the first few rows
df.head()

"""
Explanation: If we scroll we can see all of it. But maybe we don't want to see all of it. Maybe we hate scrolling?
End of explanation
"""


# Let's look at MORE of the first few rows
df.head(10)

"""
Explanation: ...but maybe we want to see more than a measly five results?
End of explanation
"""


# Let's look at the final few rows
df.tail(4)

"""
Explanation: But maybe we want to make a basketball joke and see the final four?
End of explanation
"""


# Show the 6th through the 8th rows
df[5:8]

"""
Explanation: So yes, head and tail work kind of like the terminal commands. That's nice, I guess.
But maybe we're incredibly demanding (which we are) and we want, say, the 6th through the 8th row (which we do). Don't worry (which I know you were), we can do that, too.
End of explanation
"""


# Get the names of the columns, just because
df.columns

# If we want to be "correct" we add .values on the end of it
df.columns.values

# Select only name and age
columns_to_show = ['Name', 'Age']
df[columns_to_show]

# Combing that with .head() to see not-so-many rows
columns_to_show = ['Name', 'Age']
df[columns_to_show].head()

# We can also do this all in one line, even though it starts looking ugly
# (unlike the cute bears pandas looks ugly pretty often)
df[['Name', 'Age']].head()

"""
Explanation: It's kind of like an array, right? Except where in an array we'd say df[0] this time we need to give it two numbers, the start and the end.
Selecting columns
But jeez, my eyes don't want to go that far over the data. I only want to see, uh, name and age.
End of explanation
"""


df.head()

"""
Explanation: NOTE: That was not df['Name', 'Age'], it was df[['Name', 'Age]]. You'll definitely type it wrong all of the time. When things break with pandas it's probably because you forgot to put in a million brackets.
Describing your data
A powerful tool of pandas is being able to select a portion of your data, because who ordered all that data anyway.
End of explanation
"""


# Grab the POS column, and count the different values in it.
df['POS'].value_counts()

"""
Explanation: I want to know how many people are in each position. Luckily, pandas can tell me!
End of explanation
"""


# Summary statistics for Age
df['Age'].describe()

# That's pretty good. Does it work for everything? How about the money?
df['2013 $'].describe()

"""
Explanation: Now that was a little weird, yes - we used df['POS'] instead of df[['POS']] when viewing the data's details.
But now I'm curious about numbers: how old is everyone? Maybe we could, I don't know, get some statistics about age? Some statistics to describe age?
End of explanation
"""


# Doing more describing
df['Ht (In.)'].describe()

"""
Explanation: Unfortunately because that has dollar signs and commas it's thought of as a string. We'll fix it in a second, but let's try describing one more thing.
End of explanation
"""


# Take another look at our inches, but only the first few
df['Ht (In.)'].head()

# Divide those inches by 12
df['Ht (In.)'].head() / 12

# Let's divide ALL of them by 12
feet = df['Ht (In.)'] / 12
feet

# Can we get statistics on those?
feet.describe()

# Let's look at our original data again
df.head(2)

"""
Explanation: That's stupid, though, what's an inch even look like? What's 80 inches? I don't have a clue. If only there were some wa to manipulate our data.
Manipulating data
Oh wait there is, HA HA HA.
End of explanation
"""


# Store a new column
df['feet'] = df['Ht (In.)'] / 12
df.head()

"""
Explanation: Okay that was nice but unfortunately we can't do anything with it. It's just sitting there, separate from our data. If this were normal code we could do blahblah['feet'] = blahblah['Ht (In.)'] / 12, but since this is pandas, we can't. Right? Right?
End of explanation
"""


# Can't just use .replace
df['2013 $'].head().replace("$","")

# Need to use this weird .str thing
df['2013 $'].head().str.replace("$","")

# Can't just immediately replace the , either
df['2013 $'].head().str.replace("$","").replace(",","")

# Need to use the .str thing before EVERY string method
df['2013 $'].head().str.replace("$","").str.replace(",","")

# Describe still doesn't work.
df['2013 $'].head().str.replace("$","").str.replace(",","").describe()

# Let's convert it to an integer using .astype(int) before we describe it
df['2013 $'].head().str.replace("$","").str.replace(",","").astype(int).describe()

df['2013 $'].head().str.replace("$","").str.replace(",","").astype(int)

# Maybe we can just make them millions?
df['2013 $'].head().str.replace("$","").str.replace(",","").astype(int) / 1000000

# Unfortunately one is "n/a" which is going to break our code, so we can make n/a be 0
df['2013 $'].str.replace("$","").str.replace(",","").str.replace("n/a", "0").astype(int) / 1000000

# Remove the .head() piece and save it back into the dataframe
df['millions'] = df['2013 $'].str.replace("$","").str.replace(",","").str.replace("n/a","0").astype(int) / 1000000
df.head()

df.describe()

"""
Explanation: That's cool, maybe we could do the same thing with their salary? Take out the $ and the , and convert it to an integer?
End of explanation
"""


# This is just the first few guys in the dataset. Can we order it?
df.head(3)

# Let's try to sort them
df.sort_values(by='millions').head(3)

"""
Explanation: The average basketball player makes 3.8 million dollars and is a little over six and a half feet tall.
But who cares about those guys? I don't care about those guys. They're boring. I want the real rich guys!
Sorting and sub-selecting
End of explanation
"""


# It isn't descending = True, unfortunately
df.sort_values(by='millions', ascending=False).head(3)

# We can use this to find the oldest guys in the league
df.sort_values(by='Age', ascending=False).head(3)

# Or the youngest, by taking out 'ascending=False'
df.sort_values(by='Age').head(3)

"""
Explanation: Those guys are making nothing! If only there were a way to sort from high to low, a.k.a. descending instead of ascending.
End of explanation
"""


# Get a big long list of True and False for every single row.
df['feet'] > 7

# We could use value counts if we wanted
above_seven_feet = df['feet'] > 7
above_seven_feet.value_counts()

# But we can also apply this to every single row to say whether YES we want it or NO we don't
df['feet'].head() > 7

# Instead of putting column names inside of the brackets, we instead
# put the True/False statements. It will only return the players above 
# seven feet tall
df[df['feet'] > 7]

# Or only the guards
df[df['POS'] == 'G']

# Or only the guards who make more than 15 million
df[(df['POS'] == 'G') & (df['millions'] > 15)]

# It might be easier to break down the booleans into separate variables
is_guard = df['POS'] == 'G'
more_than_fifteen_million = df['millions'] > 15
df[is_guard & more_than_fifteen_million]

# We can save this stuff
short_players = df[df['feet'] < 6.5]
short_players

short_players.describe()

# Maybe we can compare them to taller players?
df[df['feet'] >= 6.5].describe()

"""
Explanation: But sometimes instead of just looking at them, I want to do stuff with them. Play some games with them! Dunk on them~ describe them! And we don't want to dunk on everyone, only the players above 7 feet tall.
First, we need to check out boolean things.
End of explanation
"""


df['Age'].head()

# This will scream we don't have matplotlib.
df['Age'].hist()

"""
Explanation: Drawing pictures
Okay okay enough code and enough stupid numbers. I'm visual. I want graphics. Okay????? Okay.
End of explanation
"""


!pip install matplotlib

# this will open up a weird window that won't do anything
df['Age'].hist()

# So instead you run this code
%matplotlib inline

df['Age'].hist()

"""
Explanation: matplotlib is a graphing library. It's the Python way to make graphs!
End of explanation
"""


import matplotlib.pyplot as plt
plt.style.available

plt.style.use('ggplot')

df['Age'].hist()

plt.style.use('seaborn-deep')
df['Age'].hist()

plt.style.use('fivethirtyeight')
df['Age'].hist()

"""
Explanation: But that's ugly. There's a thing called ggplot for R that looks nice. We want to look nice. We want to look like ggplot.
End of explanation
"""


# Pass in all sorts of stuff!
# Most from http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.hist.html
# .range() is a matplotlib thing
df['Age'].hist(bins=20, xlabelsize=10, ylabelsize=10, range=(0,40))

"""
Explanation: That might look better with a little more customization. So let's customize it.
End of explanation
"""


df.plot(kind='scatter', x='feet', y='millions')

df.head()

# How does experience relate with the amount of money they're making?
df.plot(kind='scatter', x='EXP', y='millions')

# At least we can assume height and weight are related
df.plot(kind='scatter', x='WT', y='feet')

# At least we can assume height and weight are related
# http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.plot.html
df.plot(kind='scatter', x='WT', y='feet', xlim=(100,300), ylim=(5.5, 8))

plt.style.use('ggplot')

df.plot(kind='scatter', x='WT', y='feet', xlim=(100,300), ylim=(5.5, 8))

# We can also use plt separately
# It's SIMILAR but TOTALLY DIFFERENT
centers = df[df['POS'] == 'C']
guards = df[df['POS'] == 'G']
forwards = df[df['POS'] == 'F']
plt.scatter(y=centers["feet"], x=centers["WT"], c='c', alpha=0.75, marker='x')
plt.scatter(y=guards["feet"], x=guards["WT"], c='y', alpha=0.75, marker='o')
plt.scatter(y=forwards["feet"], x=forwards["WT"], c='m', alpha=0.75, marker='v')
plt.xlim(100,300)
plt.ylim(5.5,8)

"""
Explanation: I want more graphics! Do tall people make more money?!?!
End of explanation
"""


