Skip to main content
Workforce LibreTexts

4: Sequences and Tables

  • Page ID
    47977
  • \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)

    \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)

    \( \newcommand{\dsum}{\displaystyle\sum\limits} \)

    \( \newcommand{\dint}{\displaystyle\int\limits} \)

    \( \newcommand{\dlim}{\displaystyle\lim\limits} \)

    \( \newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\)

    ( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\)

    \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)

    \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\)

    \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)

    \( \newcommand{\Span}{\mathrm{span}}\)

    \( \newcommand{\id}{\mathrm{id}}\)

    \( \newcommand{\Span}{\mathrm{span}}\)

    \( \newcommand{\kernel}{\mathrm{null}\,}\)

    \( \newcommand{\range}{\mathrm{range}\,}\)

    \( \newcommand{\RealPart}{\mathrm{Re}}\)

    \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)

    \( \newcommand{\Argument}{\mathrm{Arg}}\)

    \( \newcommand{\norm}[1]{\| #1 \|}\)

    \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)

    \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\AA}{\unicode[.8,0]{x212B}}\)

    \( \newcommand{\vectorA}[1]{\vec{#1}}      % arrow\)

    \( \newcommand{\vectorAt}[1]{\vec{\text{#1}}}      % arrow\)

    \( \newcommand{\vectorB}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)

    \( \newcommand{\vectorC}[1]{\textbf{#1}} \)

    \( \newcommand{\vectorD}[1]{\overrightarrow{#1}} \)

    \( \newcommand{\vectorDt}[1]{\overrightarrow{\text{#1}}} \)

    \( \newcommand{\vectE}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash{\mathbf {#1}}}} \)

    \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)

    \(\newcommand{\longvect}{\overrightarrow}\)

    \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)

    \(\newcommand{\ket}[1]{\left| #1 \right>}\)
    \(\newcommand{\bra}[1]{\left< #1 \right|}\)
    \(\newcommand{\braket}[2]{\left< #1 \vphantom{#2} \right| \left. #2 \vphantom{#1} \right>}\)
    \(\newcommand{\braopket}[3]{\left< #1 \vphantom{#2}\vphantom{#3} \right| #2 \vphantom{#1}\vphantom{#3} \left| #3 \vphantom{#1}\vphantom{#2} \right>}\)
    \(\newcommand{\qmvec}[1]{\mathbf{\vec{#1}}}\)
    \(\newcommand{\op}[1]{\hat{\mathbf{#1}}}\)
    \(\newcommand{\expect}[1]{\langle #1 \rangle}\)
    \(\newcommand{\dfn}[1]{\emph{\textbf{#1}}}\)

    \(\newcommand{\avec}{\mathbf a}\) \(\newcommand{\bvec}{\mathbf b}\) \(\newcommand{\cvec}{\mathbf c}\) \(\newcommand{\dvec}{\mathbf d}\) \(\newcommand{\dtil}{\widetilde{\mathbf d}}\) \(\newcommand{\evec}{\mathbf e}\) \(\newcommand{\fvec}{\mathbf f}\) \(\newcommand{\nvec}{\mathbf n}\) \(\newcommand{\pvec}{\mathbf p}\) \(\newcommand{\qvec}{\mathbf q}\) \(\newcommand{\svec}{\mathbf s}\) \(\newcommand{\tvec}{\mathbf t}\) \(\newcommand{\uvec}{\mathbf u}\) \(\newcommand{\vvec}{\mathbf v}\) \(\newcommand{\wvec}{\mathbf w}\) \(\newcommand{\xvec}{\mathbf x}\) \(\newcommand{\yvec}{\mathbf y}\) \(\newcommand{\zvec}{\mathbf z}\) \(\newcommand{\rvec}{\mathbf r}\) \(\newcommand{\mvec}{\mathbf m}\) \(\newcommand{\zerovec}{\mathbf 0}\) \(\newcommand{\onevec}{\mathbf 1}\) \(\newcommand{\real}{\mathbb R}\) \(\newcommand{\twovec}[2]{\left[\begin{array}{r}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\ctwovec}[2]{\left[\begin{array}{c}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\threevec}[3]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\cthreevec}[3]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\fourvec}[4]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\cfourvec}[4]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\fivevec}[5]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\cfivevec}[5]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\mattwo}[4]{\left[\begin{array}{rr}#1 \amp #2 \\ #3 \amp #4 \\ \end{array}\right]}\) \(\newcommand{\laspan}[1]{\text{Span}\{#1\}}\) \(\newcommand{\bcal}{\cal B}\) \(\newcommand{\ccal}{\cal C}\) \(\newcommand{\scal}{\cal S}\) \(\newcommand{\wcal}{\cal W}\) \(\newcommand{\ecal}{\cal E}\) \(\newcommand{\coords}[2]{\left\{#1\right\}_{#2}}\) \(\newcommand{\gray}[1]{\color{gray}{#1}}\) \(\newcommand{\lgray}[1]{\color{lightgray}{#1}}\) \(\newcommand{\rank}{\operatorname{rank}}\) \(\newcommand{\row}{\text{Row}}\) \(\newcommand{\col}{\text{Col}}\) \(\renewcommand{\row}{\text{Row}}\) \(\newcommand{\nul}{\text{Nul}}\) \(\newcommand{\var}{\text{Var}}\) \(\newcommand{\corr}{\text{corr}}\) \(\newcommand{\len}[1]{\left|#1\right|}\) \(\newcommand{\bbar}{\overline{\bvec}}\) \(\newcommand{\bhat}{\widehat{\bvec}}\) \(\newcommand{\bperp}{\bvec^\perp}\) \(\newcommand{\xhat}{\widehat{\xvec}}\) \(\newcommand{\vhat}{\widehat{\vvec}}\) \(\newcommand{\uhat}{\widehat{\uvec}}\) \(\newcommand{\what}{\widehat{\wvec}}\) \(\newcommand{\Sighat}{\widehat{\Sigma}}\) \(\newcommand{\lt}{<}\) \(\newcommand{\gt}{>}\) \(\newcommand{\amp}{&}\) \(\definecolor{fillinmathshade}{gray}{0.9}\)

    In the previous chapters we learned to work with numbers and strings, two basic data types that represent a number or a text string. In this chapter we continue by exploring a grouping of numbers or strings, which is a useful way to work with large datasets.

    Suppose we need to store the names of all 15 cities in Santa Clara County, California. It would be cumbersome to create 15 str variables, each storing one city name. Instead we can create one sequence variable, called an array, that can store all 15 strings under one variable name.

    Likewise, if we want to store the names of 50 students and their quiz scores, it would be cumbersome to create 50 variables for student names and 50 variables for quiz scores. Instead we can use a table, or a DataFrame, to store all the names and all the scores under one variable name.

    Sequences or Arrays

    In data science, a common way to store a sequence of data values is with an array. An array can store multiple data values under one variable name, making it easier to refer to the sequence of data in our code.

    To create an array from a sequence of data, we use the format:

    np.array([ list of comma-separated data values ])

    In the code below we create an array named cities that can store the 15 city names in Santa Clara County.

    import numpy as np
    
    cities = np.array(['Campbell', 'Cupertino', 'Gilroy', 'Los Altos',
                       'Los Altos Hills', 'Los Gatos', 'Milpitas', 'Monte Sereno',
                       'Morgan Hill', 'Mountain View', 'Palo Alto', 'San Jose',
                       'Santa Clara', 'Saratoga', 'Sunnyvale'])
    
    print("Array of Cities:")
    print(cities)
    Output?
    Array of Cities:
    ['Campbell' 'Cupertino' 'Gilroy' 'Los Altos' 'Los Altos Hills' 'Los Gatos'
     'Milpitas' 'Monte Sereno' 'Morgan Hill' 'Mountain View' 'Palo Alto'
     'San Jose' 'Santa Clara' 'Saratoga' 'Sunnyvale']
    

    From the code above we observe that:

    • We need to import a Python module named Numpy, and typically Numpy is shortened to np.
    • The array data type is defined in Numpy, therefore np.array( ) is a function that tells Python to create an array, ready to store a sequence of multiple data values.
    • We only need to create one variable named cities, and it can store 15 strings because it is an array data type.
    • The input to the function np.array( ) is the sequence of city names, separated by comma, and surrounded by [ ] to group the names together.
      In Python when we use [ ] to group multiple values together, the grouping is called a list.

    A Numpy array is most useful when it contains numbers, because a Numpy array comes with many math functions that can be applied to all the numbers in the array.

    In the Code cell below, we create an array called temps and store the following temperatures: 61, 63, 67, 70, 73, 79, 81, 81, 81, 76, 67, 60

    The temperatures are the 12 monthly average high temperature for the city of San Jose.

    # Create an array named temps
    SJ_temps = np.array([61, 63, 67, 70, 73, 79, 81, 81, 81, 76, 67, 60])
    # Print the temps array
    print(SJ_temps)
    Output?
    [61 63 67 70 73 79 81 81 81 76 67 60]
    

    Functions for Arrays of Numbers

    Just as there are multiple useful functions for numbers and strings, there are multiple useful functions for arrays of numbers.

    Arithmetic

    When an array contains numbers, and the array is evaluated in a math expression, the arithmetic operations automatically apply to all numbers in the array.

    Suppose we want to decrease each temperature in the temps array above by two degrees, we can simply subtract 2 from the array.

    lower_temps = SJ_temps - 2
    print("Original temp:", SJ_temps)
    print("Lowered temps:", lower_temps)
    Output?
    Original temp: [61 63 67 70 73 79 81 81 81 76 67 60]
    Lowered temps: [59 61 65 68 71 77 79 79 79 74 65 58]
    

    All the arithmetic operations (add, subtract, multiply, etc.) work the same way when one operand is an array and the other operand is a number.

    If there are two arrays of numbers in an arithmetic expression, then the math operation is performed on corresponding numbers in each array.

    # Create an array of average monthly high temperatures in Los Angeles
    LA_temps = np.array([70, 69, 70, 74, 74, 78, 83, 84, 84, 81, 74, 68])
    
    # Find the temperature difference between Los Angeles and San Jose
    temp_diff = LA_temps - SJ_temps
    print("Difference in temps:", temp_diff)
    Output?
    Difference in temps: [ 9  6  3  4  1 -1  2  3  3  5  7  8]
    

    All arithmetic operations work the same way when the operands are both arrays.

    Common Array Functions

    Some useful functions when working with an array of numbers:

    • np.size( array ): returns the count of the numbers in the array
    • np.sum( array ): returns the total of all the numbers in the array
    • np.mean( array ): returns the mean or the average of all the numbers in the array
    • np.round( array ): round each number in the array to a certain number of digits after the decimal point
    • np.sort( array ): sort the numbers in the array
    print("Number of temps:", np.size(SJ_temps))
    print("Total of temps:", np.sum(SJ_temps))
    print("Average of temps:", np.mean(SJ_temps))
    print("Rounded Celsius temps:", np.round(SJ_temps - 32 * 9/5, 1))
    print("Sorted temps:", np.sort(SJ_temps))
    Output?
    Number of temps: 12
    Total of temps: 859
    Average of temps: 71.58333333333333
    Rounded Celsius temps: [ 3.4  5.4  9.4 12.4 15.4 21.4 23.4 23.4 23.4 18.4  9.4  2.4]
    Sorted temps: [60 61 63 67 67 70 73 76 79 81 81 81]
    

    Creating Arrays of Numbers

    There are two ways to create an array of numbers when we know what the sequence of numbers are:

    1. Give the sequence of numbers as input to the function np.array, as seen in the examples above.
      numbers = np.array([10, 5.2, 7, -1.3])

    2. Use the range function as input to the function np.array. The range function will automatically create a sequence of whole numbers in the range that we specify.

      There are three ways to give input to the range function:

    • range(end number): start at 0, continue to step up by 1, stop right before the end number is reached.
    • range(start number, end number): start at start number, continue to step up by 1, stop right before end number is reached.
    • range(start number, end number, step): start at start number, continue to step up or step down by step, stop right before end number is reached.
    # create an array from 0-7, step up by 1
    print("range(8):", np.array(range(8)))
    
    # create an array from 2-7, step up by 1
    print("range(2, 8):", np.array(range(2, 8)))
    
    # create an array from 2-7, step up by 3
    print("range(2, 8, 3):", np.array(range(2, 8, 3)))
    
    # create an array from 8-3, step down by 2
    print("range(8, 2, -2):", np.array(range(8, 2, -2)))
    Output?
    range(8): [0 1 2 3 4 5 6 7]
    range(2, 8): [2 3 4 5 6 7]
    range(2, 8, 3): [2 5]
    range(8, 2, -2): [8 6 4]
    

    Note that the sequence of numbers produced by the range function stops at the number closest to the end number but never reaches the end number.

    Tables or DataFrames

    In data science one of the most commonly used Python data storage is the DataFrame. A DataFrame is a table with one or more rows and columns, making it easy to associate multiple data sequences together.

    Internally a DataFrame is made of one or more arrays, where each array is one column of the DataFrame.

    Create a DataFrame with Existing Data

    Suppose we have 5 students with the following student data:

    • Names: Emma, Tin, Ali, Jeff, Maria
    • Quiz 1 scores, corresponding with the name order above: 18, 20, 15, 17, 18
    • Quiz 2 scores, corresponding with the name order above: 19, 16, 15, 16, 17

    A DataFrame or a table is a simple but effective way to organize data:

    • Each row of the table is for one student
    • Each column of the table is for one category of data: name, quiz 1 score, quiz 2 score

    With a DataFrame we can label the columns with the categories of data, making it easy to distinguish between Quiz 1 scores and Quiz 2 scores.

    To use a DataFrame, we need to work with the pandas module, which is commonly shortened to pd. Then we create a DataFrame data type with all the data we have above.

    # Work with the pandas module
    import pandas as pd
    
    # 1. Create 3 lists to store data for the 3 categories
    names = ['Emma', 'Tin', 'Ali', 'Jeff', 'Maria']
    quiz1 = [18, 20, 15, 17, 18]
    quiz2 = [19, 16, 15, 16, 17]
    
    # 2. Create a DataFrame with the 3 lists, labeling the columns with the category names
    students = pd.DataFrame({'Name': names,
                             'Quiz 1': quiz1,
                             'Quiz 2': quiz2 })
    
    # 3. Print the DataFrame
    display(students)
    Output?
      Name Quiz 1 Quiz 2
    0 Emma 18 19
    1 Tin 20 16
    2 Ali 15 15
    3 Jeff 17 16
    4 Maria 18 17

    In the code above we observe:

    • In step 1: once again the [ ] is used to group together multiple data values into a list. We name each list with a descriptive variable name.

    • In step 2: we create the DataFrame with the function:

      pd.DataFrame( )

    • Also in step 2: we put together the 3 lists and their corresponding labels by using { }. This format creates a dictionary in Python, allowing the computer to associate each label (such as Name) with its list (such as all the data in names). Then the dictionary becomes the input to the pd.DataFrame( ) function.

    • In step 3: we use the function display( ) instead of the usual print. The display() function works with the DataFrame to print in graphical format, so that we can see the column labels and each row more clearly than using print.

    Add a column to a DataFrame

    To add a column of data to the students DataFrame, we use the following format:
    DataFrame_name[ column_label ] = [ sequence of data ]

    # add a new column for Quiz 3 scores
    students['Quiz3'] = [18, 20, 19, 18, 19]
    display(students)
    Output?
      Name Quiz 1 Quiz 2 Quiz3
    0 Emma 18 19 18
    1 Tin 20 16 20
    2 Ali 15 15 19
    3 Jeff 17 16 18
    4 Maria 18 17 19

    Create a DataFrame from a File

    Typing data into a DataFrame, as in the student example above, is fine when there are few data points. But often our input data is a large dataset that's stored in a file.

    The pandas module has several functions to read in data from a file, depending on what type of file it is.

    A common file type used in data science is a CSV file, or comma separated values file, where each data record is in a row, and each row has multiple values that are separated by commas. We will work with the data file cars.csv which is from the UCI Machine Learning Repository.

    The data in the file are characteristics of different cars, such as number of cylinders, horsepower, weight, etc.

    # Read data from a CSV file, where the file is stored online (at a URL)
    
    # 1. Store the URL or location of the data file
    url = "https://commons.libretexts.org/permalink/7byKbqzMFm/99f9cde5-b5a9-479b-9318-b232a7637cb5?direct=true"
    
    # 2. Read the CSV file into a DataFrame
    cars = pd.read_csv(url)
    
    # 3. Print the DataFrame
    display(cars)
     
      mpg cylinders displacement horsepower weight acceleration model_year origin car_name
    0 18.0 8 307.0 130.0 3504.0 12.0 70 1 chevrolet chevelle malibu
    1 15.0 8 350.0 165.0 3693.0 11.5 70 1 buick skylark 320
    2 18.0 8 318.0 150.0 3436.0 11.0 70 1 plymouth satellite
    3 16.0 8 304.0 150.0 3433.0 12.0 70 1 amc rebel sst
    4 17.0 8 302.0 140.0 3449.0 10.5 70 1 ford torino
    ... ... ... ... ... ... ... ... ... ...
    387 27.0 4 140.0 86.0 2790.0 15.6 82 1 ford mustang gl
    388 44.0 4 97.0 52.0 2130.0 24.6 82 2 vw pickup
    389 32.0 4 135.0 84.0 2295.0 11.6 82 1 dodge rampage
    390 28.0 4 120.0 79.0 2625.0 18.6 82 1 ford ranger
    391 31.0 4 119.0 82.0 2720.0 19.4 82 1 chevy s-10

    392 rows × 9 columns

    In the above example the CSV file is stored online, therefore we use the pd.read_csv( ) function with the URL as the input.

    If the CSV file is stored locally on our computer, we can also use pd.read_csv( ) but we use the name of the file instead:
    DataFrame_name = pd.read_csv( CSV_filename )
    where the CSV filename ends with the extension .csv

    Get Properties of a DataFrame

    As shown in the output of the cars DataFrame, the display function automatically shows the size of the DataFrame: the number rows and columns.

    • To get the number of rows and columns without having to print the DataFrame:
      rows, columns = DataFrame_name.shape
    rows, columns = cars.shape
    print("Number of rows:", rows)
    print("Number of columns:", columns)
    Output?
    • To display the first rows or last rows:
      First rows: DataFrame name.head( num of rows )
      Last rows: DataFrame name.tail( num of rows )

      The num of rows input is optional. If there is no input, then head and tail show 5 rows.
    Number of rows: 392
    Number of columns: 9
    
    display(cars.head(3))
    Output?
      mpg cylinders displacement horsepower weight acceleration model_year origin car_name
    0 18.0 8 307.0 130.0 3504.0 12.0 70 1 chevrolet chevelle malibu
    1 15.0 8 350.0 165.0 3693.0 11.5 70 1 buick skylark 320
    2 18.0 8 318.0 150.0 3436.0 11.0 70 1 plymouth satellite
    display(cars.tail())
    Output?
      mpg cylinders displacement horsepower weight acceleration model_year origin car_name
    387 27.0 4 140.0 86.0 2790.0 15.6 82 1 ford mustang gl
    388 44.0 4 97.0 52.0 2130.0 24.6 82 2 vw pickup
    389 32.0 4 135.0 84.0 2295.0 11.6 82 1 dodge rampage
    390 28.0 4 120.0 79.0 2625.0 18.6 82 1 ford ranger
    391 31.0 4 119.0 82.0 2720.0 19.4 82 1 chevy s-10
    • To get a list of the column labels:
      DataFrame_name.columns.to_list()
    labels = cars.columns.to_list()
    print("Column labels:", labels)
    Output?
    Column labels: ['mpg', 'cylinders', 'displacement', 'horsepower', 'weight', 'acceleration', 'model_year', 'origin', 'car_name']
    

    Access Data in a DataFrame

    There are three common ways to access data in a specific column:

    1. DataFrame_name.column_name
    2. DataFrame_name['column name']
    3. DataFrame_name.iloc[:, column_index ]

    For the last option we use the column index instead of the column name. Each column in a DataFrame is numbered from left to right with an index number, starting at 0 for the left most column, and counting up as we go to the columns on the right.

    # look at the mpg or miles per gallon column
    
    mpg = cars.mpg
    display(mpg)
    Output?
    0      18.0
    1      15.0
    2      18.0
    3      16.0
    4      17.0
           ... 
    387    27.0
    388    44.0
    389    32.0
    390    28.0
    391    31.0
    Name: mpg, Length: 392, dtype: float64
    # Can you predict what column will be printed?
    
    column_index3 = cars.iloc[:,3]
    display(column_index3)
    Output?
    0      130.0
    1      165.0
    2      150.0
    3      150.0
    4      140.0
           ...  
    387     86.0
    388     52.0
    389     84.0
    390     79.0
    391     82.0
    Name: horsepower, Length: 392, dtype: float64
    # Can you predict what data will be printed?
    
    last_mpg = cars['mpg'].tail(6)
    display(last_mpg)
    Output?
    386    27.0
    387    27.0
    388    44.0
    389    32.0
    390    28.0
    391    31.0
    Name: mpg, dtype: float64

    The code in the last example above shows a programming technique called function chaining. There are two distinct steps:

    1. The output of cars['mpg'] is the mpg column of data.
    2. This column then uses tail to get the last 6 mpg values.

    The two steps are linked or chained together in one line of code.

    To get a specific data value within a column:
    DataFrame_name.iloc[ row_index, column_index ]
    Each row in a DataFrame is also numbered with an index number, starting at 0 for the first row and counting up by one as we go down the rows.

    third_mpg = cars.iloc[2, 0]  # note that the first row has index 0, so the third row has index 2
                                 # and the first column has index 0
    print("Third mpg:", third_mpg)
    Output?
    Third mpg: 18.0
    

    Arithmetic in a DataFrame

    Since each column of a DataFrame is an array, we can use arithmetic operations on a column and store the result as a new column in the DataFrame.

    Suppose we want to add a new column that shows the weight of the cars in 1000 lb units. For example, a car that weighs 2,790 lbs will have the weight displayed as 2.790.

    cars['weight_in_1000lbs'] = cars.weight / 1000
    display(cars.head(10))
     
      mpg cylinders displacement horsepower weight acceleration model_year origin car_name weight_in_tons
    0 18.0 8 307.0 130.0 3504.0 12.0 70 1 chevrolet chevelle malibu 3.504
    1 15.0 8 350.0 165.0 3693.0 11.5 70 1 buick skylark 320 3.693
    2 18.0 8 318.0 150.0 3436.0 11.0 70 1 plymouth satellite 3.436
    3 16.0 8 304.0 150.0 3433.0 12.0 70 1 amc rebel sst 3.433
    4 17.0 8 302.0 140.0 3449.0 10.5 70 1 ford torino 3.449
    5 15.0 8 429.0 198.0 4341.0 10.0 70 1 ford galaxie 500 4.341
    6 14.0 8 454.0 220.0 4354.0 9.0 70 1 chevrolet impala 4.354
    7 14.0 8 440.0 215.0 4312.0 8.5 70 1 plymouth fury iii 4.312
    8 14.0 8 455.0 225.0 4425.0 10.0 70 1 pontiac catalina 4.425
    9 15.0 8 390.0 190.0 3850.0 8.5 70 1 amc ambassador dpl 3.850

    Sort Data

    The DataFrame has a convenient method to sort data in ascending (lowest to highest) order or descending (highest to lowest) order.

    To sort data we must select a column that will be used to determine the sorting order. During the sort, the DataFrame will automatically move an entire row based on the sorting order of the selected column. This way all data in one row always stay together.

    new_DataFrame = existing_DataFrame.sort_values( by=column_name )
    The default order is ascending order.

    To sort in descending order, we need to request it:
    new_DataFrame = existing_DataFrame.sort_values( by=column_name, ascending=False )

    # create a new DataFrame with the first 5 rows of the cars DataFrame
    
    first_five = cars.head()
    display(first_five)
    Output?
      mpg cylinders displacement horsepower weight acceleration model_year origin car_name weight_in_tons
    0 18.0 8 307.0 130.0 3504.0 12.0 70 1 chevrolet chevelle malibu 3.504
    1 15.0 8 350.0 165.0 3693.0 11.5 70 1 buick skylark 320 3.693
    2 18.0 8 318.0 150.0 3436.0 11.0 70 1 plymouth satellite 3.436
    3 16.0 8 304.0 150.0 3433.0 12.0 70 1 amc rebel sst 3.433
    4 17.0 8 302.0 140.0 3449.0 10.5 70 1 ford torino 3.449
    # display the first_five DataFrame sorted by car name
    
    display(first_five.sort_values(by='car_name'))
    Output?
      mpg cylinders displacement horsepower weight acceleration model_year origin car_name weight_in_tons
    3 16.0 8 304.0 150.0 3433.0 12.0 70 1 amc rebel sst 3.433
    1 15.0 8 350.0 165.0 3693.0 11.5 70 1 buick skylark 320 3.693
    0 18.0 8 307.0 130.0 3504.0 12.0 70 1 chevrolet chevelle malibu 3.504
    4 17.0 8 302.0 140.0 3449.0 10.5 70 1 ford torino 3.449
    2 18.0 8 318.0 150.0 3436.0 11.0 70 1 plymouth satellite 3.436
    # Can you write code to do the following?
    # Display the first_five DataFrame sorted by weight_in_1000lbs, in descending order
     

    Selecting Columns

    Often in data analysis we need to work with only a section of a DataFrame and not the entire DataFrame. The DataFrame has several useful methods that we can use to select certain columns and rows that we want.

    • Create a new DataFrame with selected columns:
      new_DataFrame = existing_DataFrame[ list of column names ]
    # Recap of cars DataFrame by showing first 5 rows
    display(cars.head())
    Output?
      mpg cylinders displacement horsepower weight acceleration model_year origin car_name weight_in_tons
    0 18.0 8 307.0 130.0 3504.0 12.0 70 1 chevrolet chevelle malibu 3.504
    1 15.0 8 350.0 165.0 3693.0 11.5 70 1 buick skylark 320 3.693
    2 18.0 8 318.0 150.0 3436.0 11.0 70 1 plymouth satellite 3.436
    3 16.0 8 304.0 150.0 3433.0 12.0 70 1 amc rebel sst 3.433
    4 17.0 8 302.0 140.0 3449.0 10.5 70 1 ford torino 3.449
    # Create a DataFrame with only car names and mpg
    
    car_mpg = cars[['car_name', 'mpg']]
    display(car_mpg.head())
    print("Type of car_mpg:", type(car_mpg))
    Output?
      car_name mpg
    0 chevrolet chevelle malibu 18.0
    1 buick skylark 320 15.0
    2 plymouth satellite 18.0
    3 amc rebel sst 16.0
    4 ford torino 17.0
    Type of car_mpg: <class 'pandas.core.frame.DataFrame'>
    
    • Create a new array with one selected column:
      new_array = existing_DataFrame[ column_name ].to_numpy()
    weight_array = cars['weight_in_1000lbs'].to_numpy()
    print("Weight array:", weight_array)
    print("Type of array:", type(weight_array))
     
    Weight array: [3.504 3.693 3.436 3.433 3.449 4.341 4.354 4.312 4.425 3.85  3.563 3.609
     3.761 3.086 2.372 2.833 2.774 2.587 2.13  1.835 2.672 2.43  2.375 2.234
     2.648 4.615 4.376 4.382 4.732 2.13  2.264 2.228 2.634 3.439 3.329 3.302
     3.288 4.209 4.464 4.154 4.096 4.955 4.746 5.14  2.962 2.408 3.282 3.139
     2.22  2.123 2.074 2.065 1.773 1.613 1.834 1.955 2.278 2.126 2.254 2.408
     2.226 4.274 4.385 4.135 4.129 3.672 4.633 4.502 4.456 4.422 2.33  3.892
     4.098 4.294 4.077 2.933 2.511 2.979 2.189 2.395 2.288 2.506 2.164 2.1
     4.1   3.672 3.988 4.042 3.777 4.952 4.464 4.363 4.237 4.735 4.951 3.821
     3.121 3.278 2.945 3.021 2.904 1.95  4.997 4.906 4.654 4.499 2.789 2.279
     2.401 2.379 2.124 2.31  2.472 2.265 4.082 4.278 1.867 2.158 2.582 2.868
     3.399 2.66  2.807 3.664 3.102 2.901 3.336 1.95  2.451 1.836 2.542 3.781
     3.632 3.613 4.141 4.699 4.457 4.638 4.257 2.219 1.963 2.3   1.649 2.003
     2.125 2.108 2.246 2.489 2.391 2.    3.264 3.459 3.432 3.158 4.668 4.44
     4.498 4.657 3.907 3.897 3.73  3.785 3.039 3.221 3.169 2.171 2.639 2.914
     2.592 2.702 2.223 2.545 2.984 1.937 3.211 2.694 2.957 2.945 2.671 1.795
     2.464 2.22  2.572 2.255 2.202 4.215 4.19  3.962 4.215 3.233 3.353 3.012
     3.085 2.035 2.164 1.937 1.795 3.651 3.574 3.645 3.193 1.825 1.99  2.155
     2.565 3.15  3.94  3.27  2.93  3.82  4.38  4.055 3.87  3.755 2.045 2.155
     1.825 2.3   1.945 3.88  4.06  4.14  4.295 3.52  3.425 3.63  3.525 4.22
     4.165 4.325 4.335 1.94  2.74  2.265 2.755 2.051 2.075 1.985 2.19  2.815
     2.6   2.72  1.985 1.8   1.985 2.07  1.8   3.365 3.735 3.57  3.535 3.155
     2.965 2.72  3.43  3.21  3.38  3.07  3.62  3.41  3.425 3.445 3.205 4.08
     2.155 2.56  2.3   2.23  2.515 2.745 2.855 2.405 2.83  3.14  2.795 3.41
     1.99  2.135 3.245 2.99  2.89  3.265 3.36  3.84  3.725 3.955 3.83  4.36
     4.054 3.605 3.94  1.925 1.975 1.915 2.67  3.53  3.9   3.19  3.42  2.2
     2.15  2.02  2.13  2.67  2.595 2.7   2.556 2.144 1.968 2.12  2.019 2.678
     2.87  3.003 3.381 2.188 2.711 2.542 2.434 2.265 2.11  2.8   2.11  2.085
     2.335 2.95  3.25  1.85  2.145 1.845 2.91  2.42  2.5   2.29  2.49  2.635
     2.62  2.725 2.385 1.755 1.875 1.76  2.065 1.975 2.05  1.985 2.215 2.045
     2.38  2.19  2.21  2.35  2.615 2.635 3.23  3.16  2.9   2.93  3.415 3.725
     3.06  3.465 2.605 2.64  2.395 2.575 2.525 2.735 2.865 1.98  2.025 1.97
     2.125 2.125 2.16  2.205 2.245 1.965 1.965 1.995 2.945 3.015 2.585 2.835
     2.665 2.37  2.95  2.79  2.13  2.295 2.625 2.72 ]
    Type of array: <class 'numpy.ndarray'>
    
    • Create a new DataFrame by dropping or removing columns:
      new_DataFrame = existing_DataFrame.drop(columns=[ column_names ])
    # first we check the columns of the cars DataFrame
    cars.columns
    Output?
    Index(['mpg', 'cylinders', 'displacement', 'horsepower', 'weight',
           'acceleration', 'model_year', 'origin', 'car_name', 'weight_in_tons'],
          dtype='object')
    # suppose we only need the mpg, cylinders, horsepower, and car_name columns
    
    mpg_cyl_hp= cars.drop(columns=['displacement', 'weight', 'acceleration', 'model_year', 'origin', 'weight_in_1000lbs'])
    display(mpg_cyl_hp.head())
    print("Type of mpg_cyl_hp:", type(mpg_cyl_hp))
     
      mpg cylinders horsepower car_name
    0 18.0 8 130.0 chevrolet chevelle malibu
    1 15.0 8 165.0 buick skylark 320
    2 18.0 8 150.0 plymouth satellite
    3 16.0 8 150.0 amc rebel sst
    4 17.0 8 140.0 ford torino
    Type of mpg_cyl_hp: <class 'pandas.core.frame.DataFrame'>
    

    Selecting Rows

    Sometimes we only want certain rows of a DataFrame. We can use the row index to select one or more rows to create a new array or DataFrame.

    • Select one row: resulting in a new array
      new_array = existing_DataFrame.iloc[ row_index ].to_numpy()
    • Selecting a range of rows: resulting in a new DataFrame
      new_DataFrame = existing_DataFrame.iloc[ np.arange( start_index, end_index ) ]
    • Selecting specific rows: resulting in a new DataFrame
      new_DataFrame = existing_DataFrame.iloc( list of index values )
    first_car = cars.iloc[0].to_numpy()
    print(first_car)
    print(type(first_car))
    Output?
    [np.float64(18.0) np.int64(8) np.float64(307.0) np.float64(130.0)
     np.float64(3504.0) np.float64(12.0) np.int64(70) np.int64(1)
     'chevrolet chevelle malibu' np.float64(3.504)]
    <class 'numpy.ndarray'>
    
    first_three = cars.iloc[np.arange(0,3)]
    display(first_three)
    print(type(first_three))
    Output?
      mpg cylinders displacement horsepower weight acceleration model_year origin car_name weight_in_tons
    0 18.0 8 307.0 130.0 3504.0 12.0 70 1 chevrolet chevelle malibu 3.504
    1 15.0 8 350.0 165.0 3693.0 11.5 70 1 buick skylark 320 3.693
    2 18.0 8 318.0 150.0 3436.0 11.0 70 1 plymouth satellite 3.436
    <class 'pandas.core.frame.DataFrame'>
    
    row5_row10 = cars.iloc[[4,9]]
    display(row5_row10)
    print(type(row5_row10))
    Output?
      mpg cylinders displacement horsepower weight acceleration model_year origin car_name weight_in_tons
    4 17.0 8 302.0 140.0 3449.0 10.5 70 1 ford torino 3.449
    9 15.0 8 390.0 190.0 3850.0 8.5 70 1 amc ambassador dpl 3.850
    <class 'pandas.core.frame.DataFrame'>
    

    Conditional Selection

    Often we want to select the rows of the DataFrame based on a certain condition, such as all cars with 4 cylinders or all cars weighing more than 3 tons.

    • Select based on one condition

    We can use relational operators to compare data in a specific column and select only the True output.
    Recall that relational operators are <, >=, ==, etc.
    DataFrame_name[ DataFrame_name.column_name <relational_operator> value ]

    # All cars with 4 cylinders
    
    display(cars[cars.cylinders == 4])
    Output?
      mpg cylinders displacement horsepower weight acceleration model_year origin car_name weight_in_tons
    14 24.0 4 113.0 95.0 2372.0 15.0 70 3 toyota corona mark ii 2.372
    18 27.0 4 97.0 88.0 2130.0 14.5 70 3 datsun pl510 2.130
    19 26.0 4 97.0 46.0 1835.0 20.5 70 2 volkswagen 1131 deluxe sedan 1.835
    20 25.0 4 110.0 87.0 2672.0 17.5 70 2 peugeot 504 2.672
    21 24.0 4 107.0 90.0 2430.0 14.5 70 2 audi 100 ls 2.430
    ... ... ... ... ... ... ... ... ... ... ...
    387 27.0 4 140.0 86.0 2790.0 15.6 82 1 ford mustang gl 2.790
    388 44.0 4 97.0 52.0 2130.0 24.6 82 2 vw pickup 2.130
    389 32.0 4 135.0 84.0 2295.0 11.6 82 1 dodge rampage 2.295
    390 28.0 4 120.0 79.0 2625.0 18.6 82 1 ford ranger 2.625
    391 31.0 4 119.0 82.0 2720.0 19.4 82 1 chevy s-10 2.720

    199 rows × 10 columns

    # All cars that weigh more than 3000 lbs
    
    display(cars[cars.weight_in_1000lbs > 3])
     
      mpg cylinders displacement horsepower weight acceleration model_year origin car_name weight_in_tons
    0 18.0 8 307.0 130.0 3504.0 12.0 70 1 chevrolet chevelle malibu 3.504
    1 15.0 8 350.0 165.0 3693.0 11.5 70 1 buick skylark 320 3.693
    2 18.0 8 318.0 150.0 3436.0 11.0 70 1 plymouth satellite 3.436
    3 16.0 8 304.0 150.0 3433.0 12.0 70 1 amc rebel sst 3.433
    4 17.0 8 302.0 140.0 3449.0 10.5 70 1 ford torino 3.449
    ... ... ... ... ... ... ... ... ... ... ...
    358 22.4 6 231.0 110.0 3415.0 15.8 81 1 buick century 3.415
    359 26.6 8 350.0 105.0 3725.0 19.0 81 1 oldsmobile cutlass ls 3.725
    360 20.2 6 200.0 88.0 3060.0 17.1 81 1 ford granada gl 3.060
    361 17.6 6 225.0 85.0 3465.0 16.6 81 1 chrysler lebaron salon 3.465
    381 38.0 6 262.0 85.0 3015.0 17.0 82 1 oldsmobile cutlass ciera (diesel) 3.015

    167 rows × 10 columns

    # Can you write a line of code to print all data for the car named ford ranger?
    
    Output?

    Select based on more than one condition

    When we select data based on two or more conditions, each condition must be inside ( ).

    We can require:

    • All the conditions to be True:
      We use the operator & between the conditions.
    • Only one of the conditions needs to be True:
      We use the operator | between the conditions
    # All cars that weigh more than 3000lbs and have 4 cylinders
    
    display(cars[(cars.weight_in_1000lbs > 3) & (cars.cylinders == 4)])
     
      mpg cylinders displacement horsepower weight acceleration model_year origin car_name weight_in_tons
    205 20.0 4 130.0 102.0 3150.0 15.7 76 2 volvo 245 3.150
    207 19.0 4 120.0 88.0 3270.0 21.9 76 2 peugeot 504 3.270
    297 27.2 4 141.0 71.0 3190.0 24.8 79 2 peugeot 504 3.190
    313 24.3 4 151.0 90.0 3003.0 20.1 80 1 amc concord 3.003
    326 30.0 4 146.0 67.0 3250.0 21.8 80 2 mercedes-benz 240d 3.250
    354 28.1 4 141.0 80.0 3230.0 20.4 81 2 peugeot 505s turbo diesel 3.230
    # All cars that are model year 70 or 80
    display(cars[(cars.model_year == 70) | (cars.model_year == 80)])
    Output?
      mpg cylinders displacement horsepower weight acceleration model_year origin car_name weight_in_tons
    0 18.0 8 307.0 130.0 3504.0 12.0 70 1 chevrolet chevelle malibu 3.504
    1 15.0 8 350.0 165.0 3693.0 11.5 70 1 buick skylark 320 3.693
    2 18.0 8 318.0 150.0 3436.0 11.0 70 1 plymouth satellite 3.436
    3 16.0 8 304.0 150.0 3433.0 12.0 70 1 amc rebel sst 3.433
    4 17.0 8 302.0 140.0 3449.0 10.5 70 1 ford torino 3.449
    5 15.0 8 429.0 198.0 4341.0 10.0 70 1 ford galaxie 500 4.341
    6 14.0 8 454.0 220.0 4354.0 9.0 70 1 chevrolet impala 4.354
    7 14.0 8 440.0 215.0 4312.0 8.5 70 1 plymouth fury iii 4.312
    8 14.0 8 455.0 225.0 4425.0 10.0 70 1 pontiac catalina 4.425
    9 15.0 8 390.0 190.0 3850.0 8.5 70 1 amc ambassador dpl 3.850
    10 15.0 8 383.0 170.0 3563.0 10.0 70 1 dodge challenger se 3.563
    11 14.0 8 340.0 160.0 3609.0 8.0 70 1 plymouth 'cuda 340 3.609
    12 15.0 8 400.0 150.0 3761.0 9.5 70 1 chevrolet monte carlo 3.761
    13 14.0 8 455.0 225.0 3086.0 10.0 70 1 buick estate wagon (sw) 3.086
    14 24.0 4 113.0 95.0 2372.0 15.0 70 3 toyota corona mark ii 2.372
    15 22.0 6 198.0 95.0 2833.0 15.5 70 1 plymouth duster 2.833
    16 18.0 6 199.0 97.0 2774.0 15.5 70 1 amc hornet 2.774
    17 21.0 6 200.0 85.0 2587.0 16.0 70 1 ford maverick 2.587
    18 27.0 4 97.0 88.0 2130.0 14.5 70 3 datsun pl510 2.130
    19 26.0 4 97.0 46.0 1835.0 20.5 70 2 volkswagen 1131 deluxe sedan 1.835
    20 25.0 4 110.0 87.0 2672.0 17.5 70 2 peugeot 504 2.672
    21 24.0 4 107.0 90.0 2430.0 14.5 70 2 audi 100 ls 2.430
    22 25.0 4 104.0 95.0 2375.0 17.5 70 2 saab 99e 2.375
    23 26.0 4 121.0 113.0 2234.0 12.5 70 2 bmw 2002 2.234
    24 21.0 6 199.0 90.0 2648.0 15.0 70 1 amc gremlin 2.648
    25 10.0 8 360.0 215.0 4615.0 14.0 70 1 ford f250 4.615
    26 10.0 8 307.0 200.0 4376.0 15.0 70 1 chevy c20 4.376
    27 11.0 8 318.0 210.0 4382.0 13.5 70 1 dodge d200 4.382
    28 9.0 8 304.0 193.0 4732.0 18.5 70 1 hi 1200d 4.732
    307 41.5 4 98.0 76.0 2144.0 14.7 80 2 vw rabbit 2.144
    308 38.1 4 89.0 60.0 1968.0 18.8 80 3 toyota corolla tercel 1.968
    309 32.1 4 98.0 70.0 2120.0 15.5 80 1 chevrolet chevette 2.120
    310 37.2 4 86.0 65.0 2019.0 16.4 80 3 datsun 310 2.019
    311 28.0 4 151.0 90.0 2678.0 16.5 80 1 chevrolet citation 2.678
    312 26.4 4 140.0 88.0 2870.0 18.1 80 1 ford fairmont 2.870
    313 24.3 4 151.0 90.0 3003.0 20.1 80 1 amc concord 3.003
    314 19.1 6 225.0 90.0 3381.0 18.7 80 1 dodge aspen 3.381
    315 34.3 4 97.0 78.0 2188.0 15.8 80 2 audi 4000 2.188
    316 29.8 4 134.0 90.0 2711.0 15.5 80 3 toyota corona liftback 2.711
    317 31.3 4 120.0 75.0 2542.0 17.5 80 3 mazda 626 2.542
    318 37.0 4 119.0 92.0 2434.0 15.0 80 3 datsun 510 hatchback 2.434
    319 32.2 4 108.0 75.0 2265.0 15.2 80 3 toyota corolla 2.265
    320 46.6 4 86.0 65.0 2110.0 17.9 80 3 mazda glc 2.110
    321 27.9 4 156.0 105.0 2800.0 14.4 80 1 dodge colt 2.800
    322 40.8 4 85.0 65.0 2110.0 19.2 80 3 datsun 210 2.110
    323 44.3 4 90.0 48.0 2085.0 21.7 80 2 vw rabbit c (diesel) 2.085
    324 43.4 4 90.0 48.0 2335.0 23.7 80 2 vw dasher (diesel) 2.335
    325 36.4 5 121.0 67.0 2950.0 19.9 80 2 audi 5000s (diesel) 2.950
    326 30.0 4 146.0 67.0 3250.0 21.8 80 2 mercedes-benz 240d 3.250
    327 44.6 4 91.0 67.0 1850.0 13.8 80 3 honda civic 1500 gl 1.850
    328 33.8 4 97.0 67.0 2145.0 18.0 80 3 subaru dl 2.145
    329 29.8 4 89.0 62.0 1845.0 15.3 80 2 vokswagen rabbit 1.845
    330 32.7 6 168.0 132.0 2910.0 11.4 80 3 datsun 280-zx 2.910
    331 23.7 3 70.0 100.0 2420.0 12.5 80 3 mazda rx-7 gs 2.420
    332 35.0 4 122.0 88.0 2500.0 15.1 80 2 triumph tr7 coupe 2.500
    333 32.4 4 107.0 72.0 2290.0 17.0 80 3 honda accord 2.290
    • Select based on a partial match of a string

    If the condition is based on data which is a string, we can also look for a partial match of a given text string.
    DataFrame_name[ DataFrame_name.column_name.str.contains( "given text string", case=False ) ]

    # All cars that are from mazda
    
    display(cars[cars.car_name.str.contains("Mazda", case=False)])
    Output?
      mpg cylinders displacement horsepower weight acceleration model_year origin car_name weight_in_tons
    70 19.0 3 70.0 97.0 2330.0 13.5 72 3 mazda rx2 coupe 2.330
    241 21.5 3 80.0 110.0 2720.0 13.5 77 3 mazda rx-4 2.720
    244 32.8 4 78.0 52.0 1985.0 19.4 78 3 mazda glc deluxe 1.985
    317 31.3 4 120.0 75.0 2542.0 17.5 80 3 mazda 626 2.542
    320 46.6 4 86.0 65.0 2110.0 17.9 80 3 mazda glc 2.110
    331 23.7 3 70.0 100.0 2420.0 12.5 80 3 mazda rx-7 gs 2.420
    345 34.1 4 91.0 68.0 1985.0 16.0 81 3 mazda glc 4 1.985
    353 31.6 4 120.0 74.0 2635.0 18.3 81 3 mazda 626 2.635
    370 37.0 4 91.0 68.0 2025.0 18.2 82 3 mazda glc custom l 2.025
    371 31.0 4 91.0 68.0 1970.0 17.6 82 3 mazda glc custom 1.970

    The case=False input means that the match can be with either uppercase or lowercase letters. In the example above, the input string that we give to the selection is "Mazda" but all the matches are "mazda". We leave out the case=False if we want an exact match of uppercase or lowercase of the given text string.

    Summary

    In this chapter we learn two commonly used data types in data science: the array for a sequence of data, and the DataFrame for multiple data records, where each record has many data fields.

    These data types, together with numbers and strings, provide the tools to analyze and perform calculations with large datasets.


    This page titled 4: Sequences and Tables was last modified on Thu, 08 Oct 2026 16:26:02 GMT and is shared under a CC BY 4.0 license and was authored, remixed, and/or curated by Clare Nguyen.