To retrieve a vector for name, we can access the DataFrame with the ., as we did previously with structs in Section 3:

    1. function names_grades1()
    2. df = grades_2020()
    3. df.name
    4. end
    5. JDS.names_grades1()
    1. ["Sally", "Bob", "Alice", "Hank"]

    or we can index a DataFrame much like an Array with symbols and special characters. The second index is the column indexing:

    1. function names_grades2()
    2. df = grades_2020()
    3. df[!, :name]
    4. JDS.names_grades2()

    Note that df.name is exactly the same as df[!, :name], which you can verify yourself by doing:

    For any row, say the second row, we can use the first index as row indexing:

    1. df = grades_2020()
    2. df[2, :]

    or create a function to give us any row i we want:

    1. function grade_2020(i::Int)
    2. df = grades_2020()
    3. df[i, :]
    4. end
    5. JDS.grade_2020(2)

    We can also get only names for the first 2 rows using slicing (again similar to an Array):

    1. ["Sally", "Bob"]
    1. 5.0

    which works because zip loops through df.name and df.grade_2020 at the same time like a “zipper”:

    1. df = grades_2020()
    2. collect(zip(df.name, df.grade_2020))
    1. ("Sally", 1.0)
    1. ("Bob", 5.0)
    1. ("Hank", 4.0)

    However, converting a DataFrame to a Dict is only useful when the elements are unique. Generally that is not the case and that’s why we need to learn how to filter a DataFrame.