<jupyter_start><jupyter_text>Advanced indexing  1. Changing index of a DataFrameAs you saw in the previous exercise, indexes are immutable objects. This means that if you want to change or modify the index in a DataFrame, then you need to change the whole index. You will do this now, using a list comprehension to create the new index.A list comprehension is a succinct way to generate a list in one line. For example, the following list comprehension generates a list that contains the cubes of all numbers from 0 to 9: `cubes = [i**3 for i in range(10)]`. This is equivalent to the following code:```pythoncubes = []for i in range(10):    cubes.append(i**3)```<jupyter_code># Import required packages
import pandas as pd
# Import data
sales = pd.read_csv("data/sales/sales.csv", index_col = "month")
sales
# Create the list of new indexes: new_idx
new_idx = [x.upper() for x in sales.index]

# Assign new_idx to sales.index
sales.index = new_idx

# Print the sales DataFrame
sales<jupyter_output><empty_output><jupyter_text>Well done! Notice the DataFrame's new index!  2. Changing index name labelsNotice that in the previous exercise, the index was not labeled with a name. In this exercise, you will set its name to 'MONTHS'.Similarly, if all the columns are related in some way, you can provide a label for the set of columns.<jupyter_code># Assign the string 'MONTHS' to sales.index.name
sales.index.name = "MONTHS"

# Print the sales DataFrame
sales
# Assign the string 'PRODUCTS' to sales.columns.name 
sales.columns.name = "PRODUCTS"

# Print the sales dataframe again
sales<jupyter_output><empty_output><jupyter_text>Wonderful work! Notice how in the first DataFrame, the index has a label, and in the second DataFrame, both the index as well as the columns have labels.  3. Building an index, then a DataFrameYou can also build the DataFrame and index independently, and then put them together. If you take this route, be careful, as any mistakes in generating the DataFrame or the index can cause the data and the index to be aligned incorrectly.In this exercise, the sales DataFrame has been provided for you without the month index. Your job is to build this index separately and then assign it to the sales DataFrame.<jupyter_code># Preparing dataframe for this exercise
sales.reset_index(inplace=True)
sales.drop("MONTHS", axis = "columns", inplace=True)
sales.columns.name = None
sales
# Generate the list of months: months
months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun']

# Assign months to sales.index
sales.index = months

# Print the modified sales DataFrame
sales<jupyter_output><empty_output><jupyter_text>Excellent work! You're getting the hang of working with indexes. You'll now move onto learning about hierarchical indexes!  4. Extracting data with a MultiIndexThe sales DataFrame you have been working with has been extended to now include State information as well. Extracting elements from the outermost level of a MultiIndex is just like in the case of a single-level Index. You can use the .loc[] accessor.<jupyter_code># Importing all columns except month for this exercise
sales = pd.read_csv("data/sales/sales.csv", usecols=list(range(1,4)))
sales
# Printing type of imported dataframe index
type(sales.index)
# defining Indexing parameters
month =  [1,2,1,2,1,2]
state = ["CA","CA", "NY", "NY", "TX", "TX"]
index_names = ["state", "month"]
# Setting Multi-level index
sales.index = [state, month]
sales.index.names = index_names
sales
# Print sales.loc[['CA', 'TX']]
sales.loc[["CA", "TX"]]
# Print sales['CA':'TX']
sales['CA':'TX']
# Printing the multilevel index
sales.index
# Printing type of index.name
type(sales.index.name)
# Printing type of index.names
type(sales.index.names)<jupyter_output><empty_output><jupyter_text>Well done! Notice how New York is excluded by the first operation, and included in the second one.  5. Setting & sorting a MultiIndexIn the previous exercise, the MultiIndex was created and sorted for you. Now, you're going to do this yourself! With a MultiIndex, you should always ensure the index is sorted. You can skip this only if you know the data is already sorted on the index fields.<jupyter_code># Preparing the dataframe for this exercise
sales.reset_index(inplace = True)
sales
# Set the index to be the columns ['state', 'month']: sales
sales = sales.set_index(["state", "month"])

# Sort the MultiIndex: sales
sales = sales.sort_index()

# Print the sales DataFrame
sales<jupyter_output><empty_output><jupyter_text>Great work! Take a look at the sorted MultiIndex!  6. Using `.loc[]` with nonunique indexesIt is always preferable to have a meaningful index that uniquely identifies each row. Even though pandas does not require unique index values in DataFrames, it works better if the index values are indeed unique. To see an example of this, you will index your sales data by `'state'` in this exercise.<jupyter_code># Preparing the dataframe for this exercise
sales.reset_index(inplace = True)
# Set the index to the column 'state': sales
sales = sales.set_index("state")

# Print the sales DataFrame
sales
# Access the data from 'NY'
sales.loc["NY"]<jupyter_output><empty_output><jupyter_text>Fantastic work! Here, because you have nonunique indexes, two rows are returned.  7. Indexing multiple levels of a MultiIndexLooking up indexed data is fast and efficient. And you have already seen that lookups based on the outermost level of a MultiIndex work just like lookups on DataFrames that have a single-level Index.Looking up data based on inner levels of a MultiIndex can be a bit trickier. In this exercise, you will use your sales DataFrame to do some increasingly complex lookups.The trickiest of all these lookups are when you want to access some inner levels of the index. In this case, you need to use `slice(None)` in the slicing parameter for the outermost dimension(s) instead of the usual `:`, or use `pd.IndexSlice`. You can refer to the pandas documentation for more details. For example, we can use the following code to extract rows from all Symbols for the dates Oct. 3rd through 4th inclusive:`stocks.loc[(slice(None), slice('2016-10-03', '2016-10-04')), :]`Pay particular attention to the tuple `(slice(None), slice('2016-10-03', '2016-10-04'))`.<jupyter_code># Preparing the dataframe for this exercise
sales.reset_index(inplace = True)
sales.set_index(["state", "month"], inplace = True)
sales
# Look up data for NY in month 1: NY_month1 - Method 1
NY_month1 = sales.loc["NY",1 ]
NY_month1
# Look up data for NY in month 1: NY_month1 - Method 2
NY_month1 = sales.loc[("NY", 1), :]
NY_month1<jupyter_output><empty_output><jupyter_text>Note: Cannot do this```python Look up data for CA and TX in month 2: CA_TX_month2sales.loc[["CA", "TX"], 2]TypeError: cannot do label indexing on  with these indexers [2] of ```<jupyter_code># Look up data for CA and TX in month 2: CA_TX_month2
CA_TX_month2 = sales.loc[(["CA", "TX"], 2),:]
CA_TX_month2<jupyter_output><empty_output><jupyter_text>Note: Cannot also do this```python Access the inner month index and look up data for all states in month 2: all_month2sales.loc[(:, 2), :]  File "", line 2    all_month2 = sales.loc[(:, 2), :]                            ^SyntaxError: invalid syntax```<jupyter_code># Access the inner month index and look up data for all states in month 2: all_month2
all_month2 = sales.loc[(slice(None), 2), :]
all_month2<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.0879106085083468, 'fraction_numerical': 0.011981690899299947, 'mean_word_length': 5.0793780687397705, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '264588', 'license': 'MIT', 'n_tokens_mistral': 2275, 'n_tokens_neox': 2132, 'n_words': 993, 'path': 'Datacamp Assignments/Data Science Track/Manipulating DataFrames with pandas/2. Advanced indexing.ipynb', 'repo_name': 'Ali-Parandeh/Data_Science_Playground', 'size': '7428'}