In [ ]:
import pandas as pd

pd.set_option('display.max_columns', 500)

def a1_notation(n):
    string = ""
    while n > 0:
        n, remainder = divmod(n - 1, 26)
        string = chr(65 + remainder) + string
    return string

alist = list(range(1, 31))
A1_list = [a1_notation(x) for x in alist]
df = pd.DataFrame([alist for aline in alist], columns=A1_list)
df

In [ ]:
# Pandas encourages use of iloc and loc to select data from DataFrames. 
# iloc uses index-based numberic indexes while loc uses row and column labels.
# If you feed only an integer to iloc, you'll get back that row as a Pandas Series (not as a DataFrame)

df.iloc[0]

In [ ]:
# We generally want DataFrames back. Simply feed iloc a list instead of an interger to get a DataFrame.
df.iloc[[0]]

In [ ]:
# Since it is a list, you can "call out" whichever rows you want by their index. 
df.iloc[[0, 2, 4, 6, 8, 10]]

In [ ]:
# Until you see a comma outside a list, you're always dealing with rows. You can get rows by slice.
df.iloc[5:10]

In [ ]:
# As with Python slices, you can leave out begining or ending values to specify begin or end.
df.iloc[25:]

In [ ]:
# A with any Python slices, this is a way to say "from beginning to end" (a.k.a. all rows):
df.iloc[:]

In [ ]:
# This is how we say from row 25 to the row prior to the last row. Again, notice the row-bias of iloc.
df.iloc[25:-1]

In [ ]:
# This is how we say from the first row to the row twenty-five prior to the last row.
df.iloc[:-25]

In [ ]:
# Now we can expose the second argument to the iloc interface using a comma. 
# It's almost the same as df.iloc[:,] but we can see where column-specifiers go.
df.iloc[:, ]

In [ ]:
# Likewise as with specifiying rows, using just a colon asks for all columns.
df.iloc[:, :]

In [ ]:
# We have the same API for selecting columns by index as we do rows. It just comes after the comma.
df.iloc[:, 0:5]

In [ ]:
# We can leave the 0 out as a shortcut for "from beginning". 
df.iloc[:, :5]

In [ ]:
# As with Python slices and the rows, we can leave out the slice's end-value, meaning "to the end".
df.iloc[:, 25:]

In [ ]:
# After the comma, the same rules apply to columns as to rows. 
# So an interger will get that column as a Pandas Series.
df.iloc[:, 0]

In [ ]:
# This is another way of saying all-rows and all-columns by slice definition.
df.iloc[:, :]

In [ ]:
# Exactly as with rows, turning the value after the comma into a list gives you those columns.
df.iloc[:, [0]]

In [ ]:
# This is just like how we picked rows with a list, but with columns.
# Put a colon comma ( :, ) at the beginning of an iloc row argument it becomes a column argument.
df.iloc[:, [0, 2, 4, 6, 8, 10]]

In [ ]:
# This is how we can combine column index-selection by list with row index-selection by list.
df.iloc[[0, 2, 4, 6, 8, 10], [0, 2, 4, 6, 8, 10]]

In [ ]:
# We can use references (variable-names) in place of lists.
alist = [0, 2, 4, 6, 8, 10]
df.iloc[alist, alist]

In [ ]:
# Slice definitions work the same way. This is the intersection of the first 5 rows and first 5 columns.
df.iloc[:5, :5]

In [ ]:
# This is how you select all columns from index location 25 to end.
df.iloc[:, 25:]

In [ ]:
# This is how you select all columns from 5 positions back from the end to the end.
df.iloc[:, -5:]

In [ ]: