{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Lab 6: Pandas" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this lab, we'll work through some of the basics of using Pandas, using a few different tabular data sets. Ultimately, one need not do anything particularly fancy with DataFrames for them to be useful as data containers. But we would like to highlight a few extra abilities these objects have, that illustrate situations where we may actually have a strong reason to use pandas over another library. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Problem 1: HII regions + Planetary Nebulae measurements in M81\n", "\n", "For our first data set, we're going to look at a file (`table2.dat`), which contains measurements of the flux and intensity of various ions' line emission from a set of known emitting objects (PNs and HII regions) in the M81 galaxy. \n", "\n", "The columns of this file are `name`, `ion`, `wl`, `flux`, and `I` (intensity). Two of the columns are string-valued (name and ion), three are numerical-values (wl, flux, I). This mix of strings and floats tells us before we even decide how to read in this file that `numpy` data structures won't be usable, as they demand all values in an array to have the same `dtype`. \n", "\n", "### Problem 1.1 \n", "\n", "Using the `pd.read_csv()` function shown in the lecture, read this data file into a dataframe called `df`, and print it. \n", "```{hint}\n", "You can get a \"pretty\" visualization of a dataframe by simply typing its name into a jupyter cell -- as long as it's the last line of the cell, the dataframe will print more nicely than typing `print(df)`. This does not work outside of notebooks.\n", "```" ] }, { "cell_type": "code", "execution_count": 83, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", "import pandas as pd\n", "%matplotlib inline \n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Problem 1.2 \n", "\n", "Though it doesn't show up in the clean representation above, the strings associated with the name and ion columns above have trailing and leading spaces that we don't want. \n", "\n", "Use a *list comprehension* to modify the data frame such that each value in the name and ion columns are replaced with a `.strip()` version of themselves." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Problem 1.3 \n", "\n", "Write a function `select_object` which takes in as an argument the name of an HII region or planetrary nebula, and filters the dataframe for only the entries for that object using `df.loc[]`. Consider having the dataframe be an optional argument you set to `df`, the dataframe we are \n", "working with.\n", "\n", "Have your function take in an optional argument `drop_empty=True` which additionally selects only those rows where the flux/intensity is **not** zero." ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
nameionwlfluxrmsI
0PN3m[OII]3727373.958.6517.3
8PN3mHI434050.03.558.0
15PN3mHI4861100.04.5100.0
16PN3m[OIII]495935.43.834.4
17PN3m[OIII]5007104.25.299.9
19PN3m[NII]57551.30.31.1
20PN3mHeI58769.10.37.2
24PN3m[NII]654859.83.542.2
25PN3mHI6563412.06.9290.1
26PN3m[NII]6584142.54.5100.0
28PN3m[SII]671760.33.841.4
29PN3m[SII]673144.33.430.4
\n", "
" ], "text/plain": [ " name ion wl flux rms I\n", "0 PN3m [OII] 3727 373.9 58.6 517.3\n", "8 PN3m HI 4340 50.0 3.5 58.0\n", "15 PN3m HI 4861 100.0 4.5 100.0\n", "16 PN3m [OIII] 4959 35.4 3.8 34.4\n", "17 PN3m [OIII] 5007 104.2 5.2 99.9\n", "19 PN3m [NII] 5755 1.3 0.3 1.1\n", "20 PN3m HeI 5876 9.1 0.3 7.2\n", "24 PN3m [NII] 6548 59.8 3.5 42.2\n", "25 PN3m HI 6563 412.0 6.9 290.1\n", "26 PN3m [NII] 6584 142.5 4.5 100.0\n", "28 PN3m [SII] 6717 60.3 3.8 41.4\n", "29 PN3m [SII] 6731 44.3 3.4 30.4" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Your function should produce the following " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Problem 1.4 \n", "\n", "Write a function `select_ion_by_wavelength()` which takes in the name of an ion and its wavelength (and a dataframe), and returns the filtered data frame for all objects, but only ions for the selected wavelengths. \n", "\n", "As before, have a `drop_empty` optional argument to not include entries where the flux and intensity are zero.\n", "\n", "Additionally, as the index is now uniquely identified by the name of the PN/HII region, set the index to be the name column." ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Problem 1.5\n", "It will be helpful to know for a given ion which wavelengths are avalable and have data in the dataframe. Write a function `get_wavelenghs_by_ion()` that determines for a given input ion, which wavelengths are available. \n", "\n", "**Bonus + 0.5: Some ions of forbidden transitions like `[OII]` have brackets in the name. Add a bit to your get_wavelengths_by_ion code that allows the user to enter either `\"[OII]\"` or `\"OII\"` and get the same answer.**\n", "\n", "Additionally, make a convenience function `get_ions()` that just returns the full list of ions represented in the dataframe.\n", "\n", "```{hint}\n", "The `.unique()` method in pandas will be useful here.\n", "```\n", "\n", "**Show that your function works by selecting the wavelengths for `[NII]` and `[OII]`.**" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array(['[OII]', 'HeI', 'HI', '[NeIII]', '[NeIII]/HI', '[SII]', '[OIII]',\n", " 'HeII', 'HeI/[ArIV]', '[ArIV]', '[NII]', '[OI]', '[SIII]', '[ArV]',\n", " '[ArIII]'], dtype=object)" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Your function should produce the following " ] }, { "cell_type": "code", "execution_count": 250, "metadata": {}, "outputs": [], "source": [ "# Show [NII]" ] }, { "cell_type": "code", "execution_count": 251, "metadata": {}, "outputs": [], "source": [ "# Show [OII]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Problem 1.6 \n", "\n", "Rather than having all these convenience functions littered around our code, let's go ahead and make a class, `FluxTable`, which initializes with our dataframe, and then has all of the functions created above as methods. The input DataFrame, `df`, should be accessible as an attribute as well. \n", "\n", "When you're done, you should be able to do something like the following \n", "```\n", "ions = FluxTable(df)\n", "print(ions.df)\n", "ions.get_ions()\n", "ions.get_wavelengths_by_ions('[OII]')\n", "PN3m = ions.select_object('PN3m')\n", "```" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [], "source": [ "# Your Class Here" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Show that your class works by running the above examples.**" ] }, { "cell_type": "code", "execution_count": 253, "metadata": {}, "outputs": [], "source": [ "# Run Get ions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Bonus: (+1) Problem 1.7 \n", "\n", "Finally, let's add one final method to our class. This method will be called `query`, and it will act as a bit of a \"catch all\", allowing the user to query for certain conditions as desired. \n", "\n", "Your `query` method should take as it's primary argument a string containing a comma separated list of desired columns. It should then have optional arguments for `name`, `ion`, and `wl`, which are by default set to `None`. For name and ion, the goal is to allow the user to specify specific ones. For `wl`, we'll go one step further and allow either a specific wavelength, or a range of wavelengths input as a string of the form `>4343` or `<3050` or `2010-5000`. \n", "\n", "The usage of this method will look something like \n", "\n", "```\n", "ft.query('name,flux',ion='[OII]',wl='3000-5000')\n", "```\n", "\n", "You will of course need to do some string checking (particularly with wl) to figure out what the user wants, and then you can use your filtering methods you already wrote to successfully construct a result dataframe to return." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Problem 2\n", "\n", "In this problem, we're going to use the [3DHST catalog](https://archive.stsci.edu/prepds/3d-hst/), which contains numerous measurements of galaxies at high redshift taken with HST. This program was led at Yale(!) and the \"3D\" refers to the fact that beyond just imaging, spectroscopic information was also obtained. \n", "\n", "We'll be using a subset of the catalog set up for the GOODS-South field, a well studied patch of the sky. The data are split across four `fits` files -- but we'll be using `pandas` to join them together! \n", "\n", "- the `.cat` file contains the primary catalog \n", "- the `.fout` file contains the output of `FAST`, a quick template fitting program for galaxies. \n", "- the `.RF` file contains the Rest Frame (de-redshifted) colors of the galaxies in common bands\n", "- the `.zout` file contains redshift estimates for all galaxies (either spec-z or photo-z) made using the EAZY redshift fitting code (also Yale!) \n", "\n", "### Problem 2.1\n", "\n", "**Load the four datasets into Python, and create dataframes for each.** For ease of following the solutions, we suggest you name these\n", "\n", "- `cat_df` for the catalog\n", "- `fast_df` for the fast output\n", "- `rf_df` for the RF file \n", "- `z_df` for the redshifts\n", "\n", "**Examine each of these dataframes to see what types of columns they have.**\n", "\n", "```{hint}\n", "Remember that the default extension for tabular data (as this is) will be 1, not 0 as we are used to for images. You can run pd.DataFrame() directly on the data attribute of this extension\n", "```" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [], "source": [ "from astropy.io import fits" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [], "source": [ "# create cat_df " ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
idxyradecfaper_f160weaper_f160wfaper_f140weaper_f140wf_f160w...irac2_contamirac3_contamirac4_contamcontam_flagf140w_flaguse_photnear_starnexp_f125wnexp_f140wnexp_f160w
0111876.6391632.89053.093012-27.95454655.1427550.046190-99.000000-99.000000152.454867...0.0000310.0001870.00117400104.00.04.0
1212056.7151321.05553.089613-27.9597420.5300630.077372-99.000000-99.0000000.638394...-99.000000-99.000000-99.00000000002.00.01.0
2311351.8751327.24453.102913-27.9596420.4677910.200590-99.000000-99.0000000.714355...-99.000000-99.000000-99.00000000001.00.01.0
3411415.6811396.83653.101709-27.95848112.4973840.086093-99.000000-99.00000027.270285...0.0573950.2063470.00065600102.00.02.0
4511385.5701384.72953.102277-27.9586831.1017400.087183-99.000000-99.0000001.412912...2.0275360.575527-2.65354310102.00.02.0
..................................................................
50502505033207.81118767.99853.256225-27.6689000.0838310.0175990.0090530.0830010.151608...-0.858407-99.000000-99.000000001024.04.026.0
50503505043319.07718889.40453.254129-27.6668790.0305840.0175990.0791410.0823960.033300...-1.151515-99.000000-99.000000000024.04.026.0
50504505057634.09118915.90853.172928-27.6664900.3030360.024853-99.000000-99.0000000.555012...1.567742-0.129032-1.21509410106.00.06.0
50505505068669.85918840.10053.153437-27.6677590.4164490.024596-99.000000-99.0000000.526232...1.1828790.794521-0.66896610016.00.06.0
50506505073041.90318822.67053.259346-27.6679860.0301830.0175990.0111910.0841540.036352...-99.000000-99.000000-99.000000000024.04.026.0
\n", "

50507 rows × 141 columns

\n", "
" ], "text/plain": [ " id x y ra dec faper_f160w \\\n", "0 1 11876.639 1632.890 53.093012 -27.954546 55.142755 \n", "1 2 12056.715 1321.055 53.089613 -27.959742 0.530063 \n", "2 3 11351.875 1327.244 53.102913 -27.959642 0.467791 \n", "3 4 11415.681 1396.836 53.101709 -27.958481 12.497384 \n", "4 5 11385.570 1384.729 53.102277 -27.958683 1.101740 \n", "... ... ... ... ... ... ... \n", "50502 50503 3207.811 18767.998 53.256225 -27.668900 0.083831 \n", "50503 50504 3319.077 18889.404 53.254129 -27.666879 0.030584 \n", "50504 50505 7634.091 18915.908 53.172928 -27.666490 0.303036 \n", "50505 50506 8669.859 18840.100 53.153437 -27.667759 0.416449 \n", "50506 50507 3041.903 18822.670 53.259346 -27.667986 0.030183 \n", "\n", " eaper_f160w faper_f140w eaper_f140w f_f160w ... irac2_contam \\\n", "0 0.046190 -99.000000 -99.000000 152.454867 ... 0.000031 \n", "1 0.077372 -99.000000 -99.000000 0.638394 ... -99.000000 \n", "2 0.200590 -99.000000 -99.000000 0.714355 ... -99.000000 \n", "3 0.086093 -99.000000 -99.000000 27.270285 ... 0.057395 \n", "4 0.087183 -99.000000 -99.000000 1.412912 ... 2.027536 \n", "... ... ... ... ... ... ... \n", "50502 0.017599 0.009053 0.083001 0.151608 ... -0.858407 \n", "50503 0.017599 0.079141 0.082396 0.033300 ... -1.151515 \n", "50504 0.024853 -99.000000 -99.000000 0.555012 ... 1.567742 \n", "50505 0.024596 -99.000000 -99.000000 0.526232 ... 1.182879 \n", "50506 0.017599 0.011191 0.084154 0.036352 ... -99.000000 \n", "\n", " irac3_contam irac4_contam contam_flag f140w_flag use_phot \\\n", "0 0.000187 0.001174 0 0 1 \n", "1 -99.000000 -99.000000 0 0 0 \n", "2 -99.000000 -99.000000 0 0 0 \n", "3 0.206347 0.000656 0 0 1 \n", "4 0.575527 -2.653543 1 0 1 \n", "... ... ... ... ... ... \n", "50502 -99.000000 -99.000000 0 0 1 \n", "50503 -99.000000 -99.000000 0 0 0 \n", "50504 -0.129032 -1.215094 1 0 1 \n", "50505 0.794521 -0.668966 1 0 0 \n", "50506 -99.000000 -99.000000 0 0 0 \n", "\n", " near_star nexp_f125w nexp_f140w nexp_f160w \n", "0 0 4.0 0.0 4.0 \n", "1 0 2.0 0.0 1.0 \n", "2 0 1.0 0.0 1.0 \n", "3 0 2.0 0.0 2.0 \n", "4 0 2.0 0.0 2.0 \n", "... ... ... ... ... \n", "50502 0 24.0 4.0 26.0 \n", "50503 0 24.0 4.0 26.0 \n", "50504 0 6.0 0.0 6.0 \n", "50505 1 6.0 0.0 6.0 \n", "50506 0 24.0 4.0 26.0 \n", "\n", "[50507 rows x 141 columns]" ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#When you look at cat_df it should look like this" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [], "source": [ "# Make fast_df " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# look at it" ] }, { "cell_type": "code", "execution_count": 254, "metadata": {}, "outputs": [], "source": [ "#Make rf_df " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# look at it" ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [], "source": [ "# make z_df " ] }, { "cell_type": "code", "execution_count": 255, "metadata": {}, "outputs": [], "source": [ "# look at it" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Problem 2.2 \n", "\n", "You should notice that every one of these tables has 50507 rows. This is a relief! It means the creators were consistent, and that each object has a row in each table. \n", "\n", "You should also notice one column, `id`, is a unique identifier for each row in each table (and is consistent across tables). Pandas has assigned its own index (it's off by 1 from the id column), but we might as well use `id`. \n", "\n", "**For each of your four dataframes, set 'id' to be the index column. Show one of the df's to show this worked.**" ] }, { "cell_type": "code", "execution_count": 49, "metadata": {}, "outputs": [], "source": [ "# overwrite dataframes to have 'id' as index" ] }, { "cell_type": "code", "execution_count": 256, "metadata": {}, "outputs": [], "source": [ "# Show one of your dataframes to confirm this worked. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Problem 2.3 \n", "\n", "Instead of working with these four dataframes separately, let's join them all into one MEGA DATAFRAME. \n", "\n", "By setting 'id' as the index for each, we'll be able to merge the dataframes using `pd.merge` with the `left_index` and `right_index` parameters set to true. \n", "\n", "**Create your mega dataframe, which we'll simply call `df`, by consecutively merging the first two, then third and fourth dataframes.**\n", "\n", "```{hint}\n", "You should end up with 215 columns in your final dataframe.\n", "```" ] }, { "cell_type": "code", "execution_count": 257, "metadata": {}, "outputs": [], "source": [ "#Merge the dataframes" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Problem 2.4 \n", "\n", "Let's take a look at the redshift distribution of sources in the catalog.\n", "\n", "There are several estimates of the photometric redshift, the one we want to use is `z_peak` for photometry, or, if available, `z_spec_x`, from spectroscopy. \n", "\n", "**What percentage of the catalog have measured spectroscopic redshifts? The `z_spec_x` column is set to `-1` if no spectroscopic redshift exits.**" ] }, { "cell_type": "code", "execution_count": 258, "metadata": {}, "outputs": [], "source": [ "# calculate here" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Problem 2.5 \n", "\n", "Write a function `get_redshift()` which takes in an object ID, and returns `z_spec_x` for that source if it's not -1, otherwise returns `z_peak`. Because `id` is a special word in python, we suggest using `objid` as the input, and setting df=df as an optional argument. You can make this a memory lite function by using `df.loc[]` to pull the row and only the two columns you need for this.\n", "\n", "There are two additional \"flagged\" values: -99.0 and -99.9 -- Have your function output np.nan if this is the value in the table. \n", "\n", "Your function should return the redshift as well as a flag (string) 's' or 'p', or 'f' for spectroscopic or photometric (or fail, if you're returning nan). " ] }, { "cell_type": "code", "execution_count": 107, "metadata": {}, "outputs": [], "source": [ "#Your get redshift function here " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Confirm your function works by testing it on objid 150; your results should match mine below:" ] }, { "cell_type": "code", "execution_count": 108, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(1.6689, 'p')" ] }, "execution_count": 108, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Run your function " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Problem 2.6 \n", "\n", "Now that we can get the best redshift for each row, use a list comprehension to grab these values for every object. You can index the output tuple of your function at 0 to drop the flag for now. \n", "\n", "Once you have this, plot a histogram of the redshifts, using `fig, ax = plt.subplots`. Make your plot nice!\n", "\n", "```{note}\n", "My list comprehension takes ~15 seconds to run. It's a lot of data! If you wish, you may try to find a more optimized solution built on a full column operation rather than a loop. One possibility is to take the spec-z column, mask any bad values, and then replace those entries in the z-phot column and plot that... \n", "```" ] }, { "cell_type": "code", "execution_count": 109, "metadata": {}, "outputs": [], "source": [ "#Get all (best) redshifts" ] }, { "cell_type": "code", "execution_count": 110, "metadata": {}, "outputs": [], "source": [ "# We suggest making it an array after the list comprehension. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```{hint}\n", "You'll want to index just the non-nan values to make your plot. You can access the non-nan elements in an array via `arr[~np.isnan(arr)]`, with the tilde serving to invert the selection.\n", "```" ] }, { "cell_type": "code", "execution_count": 113, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "# Your plot here, mine for reference " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Problem 2.7\n", "\n", "Now do the same, but separately plot the distributions of redshift for those with spectroscopic redshifts and those that only have photometric. For this, you'll want to set `density=True` in your `hist`, and play with the linestyles and opacities so that both are visible. \n", "\n", "**Bonus (+0.5): Use KDE from seaborn to smoothly represent the distribution**. " ] }, { "cell_type": "code", "execution_count": 114, "metadata": {}, "outputs": [], "source": [ "# build specz list " ] }, { "cell_type": "code", "execution_count": 115, "metadata": {}, "outputs": [], "source": [ "# build photz list " ] }, { "cell_type": "code", "execution_count": 143, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAisAAAIYCAYAAACsQKwrAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8rg+JYAAAACXBIWXMAAAsTAAALEwEAmpwYAAA4/UlEQVR4nO3deZye873/8dcnkUSINRsSJEIsJZZGlNpDxFJRdagW5SCWVlXbIw5RE0tbrbWnVMe+VJVTyq9yqC1SlZTQzS4lISESUhUSS+T7++O+Z0wmM5NrJvdyzczr+XjMI3Nf1/e+7s9c0c473+2KlBKSJEl51aXaBUiSJLXEsCJJknLNsCJJknLNsCJJknLNsCJJknLNsCJJknJtpWoX0FZ9+vRJgwYNKsu1582bR9++fcty7Y7I+9V63rPW8X61nvesdbxfrVfqe/bUU0+9nVJq8oLtNqwMGjSIadOmleXaw4cPL9u1OyLvV+t5z1rH+9V63rPW8X61XqnvWUTMbO6cw0CSJCnXDCuSJCnXDCuSJCnXDCuSJCnXDCuSJCnXDCuSJCnX2u3S5XIaO3ZstUtoV7xfrec9ax3vVzbvvfcec+fO5ZNPPuHKK6/k+eefr3ZJ7Yb3q/Wy3rNu3brRr18/Vl999TZ/VqSU2vzmaho+fHhyTbwkFbz33nu89dZbDBgwgJ49exIR1S5JIqXEokWLmD17Nv37928xsETEUyml4U2dcxhIkjqAuXPnMmDAAFZZZRWDinIjIlhllVUYMGAAc+fObfN1DCuS1AF88skn9OzZs9plSE3q2bMnn3zySZvfb1iRpA7CHhXl1Yr+t2lYkSRJuWZYkSRJuebSZUnqwEZc8GBVP/+Js/Zq83t/97vfcckll/DCCy+wYMEC+vXrx7bbbsuJJ57I6NGjS1hl6+t65ZVX+O53v1u1GiplxowZDB48mOuvv56jjz66anXYsyJJyp2f/exnfPnLX2aTTTbh2muv5d5772X8+PEAPPzww1WtrS5EdQbrrrsuU6ZMYf/9969qHfasSJJy56KLLuKggw7i2muvrT+25557cvzxx7NkyZIqVtY6H330ET169Kh2GW3Wo0cPvvCFL1S7DHtWJEn5M3/+fNZZZ50mz3Xp8tmvrhtuuIGIYPLkyRx00EH06tWL3r17881vfpNFixYt9b6FCxcybtw4Bg8eTPfu3Rk8eDAXXHDBMuFn3rx5nHzyyay//vr06NGD9ddfnyOPPJKPPvqIo48+mhtvvJHZs2cTEUQEgwYNAmDSpElEBHfeeSfHH388ffv2pX///kBhafn48eMZNGgQ3bt3Z9CgQYwfP36p5byLFy/m7LPPZsiQIay88sr06dOHnXfemccee2yp+q6++mq22247evbsyVprrcVuu+3G448/Xn/+zTff5KijjqJPnz706NGDYcOGccsttyx1jaz3bcaMGUQEN9xww1Lvf/TRR9l7771ZY401WHXVVdl6662XCpalZs+KJCl3RowYwY033shGG23EmDFjGDp0aIvtjzjiCA499FBOPvlknnjiCc4991w++OCD+l+yixcvZp999uG5557j7LPPZquttmLq1Kmcd955zJ8/n4svvhiAf/3rX+y0007Mnz+f8ePHM2zYMObOncvdd9/Nxx9/zNlnn828efN48sknueeeewCW6Tk55ZRT2Hfffbn55pv58MMPAfjGN77B7bffzplnnsnOO+/MlClTOP/883nllVe49dZbAbjwwgu59NJLueCCC9hmm2147733mDZtGvPnz6+/9ve//30uvvhijj32WCZMmECXLl2YOnUqr732GjvttBMffPABu+22G//617/44Q9/yPrrr88tt9zCkUceycKFC5d5dMXy7ltT7r77br7yla/wxS9+kV/+8pf06dOHZ599lpkzZy7/L7aNDCuSpNy56qqrOOSQQzj99NM5/fTT6d27N3vvvTfHHHMMo0aNWqb9fvvtx0UXXQTAqFGjiAh+8IMfcOaZZzJ06FB+/etf89hjj/Hoo4+y6667AjBy5EgAJkyYwLhx4+jXrx+XXnopr7zyCtOmTWPbbbetv/7hhx8OwGqrrUbfvn3p3r17s8MjI0aM4Jprrql//cwzz/DrX/+ac845h5qamvoau3btytlnn80ZZ5zBsGHDmDJlCqNGjeLUU0+tf++XvvSl+u+nT5/OpZdeymmnnbbUnJmG80muv/56Xn75ZR555BF23313APbdd1/eeustxo8fz7HHHkvXrl0z37fGUkqceuqpbLPNNjzyyCP1vVx77dX2idRZOAwkScqdoUOH8pe//IVHH32Us846i2222Ya77rqLffbZh/PPP3+Z9oceeuhSr7/61a+yZMkSnnjiCQDuu+8+NtxwQ3baaScWL15c/zVq1Cg++eQTpk6dCsAf/vAHtt9++6WCSmt9+ctfXur15MmTgUIvRkN1rx999FEAtt9+eyZOnMhZZ53FY489xscff7xU+wcffJAlS5a0+GDPyZMnM2DAgPqg0vCz5s2bx3PPPbfU8eXdt8ZefPFFZs6cyXHHHbfUcFy52bPSTtWl80q9T5IqrWvXruy66671PSFvvPEGo0ePZsKECXzzm99krbXWqm9bNzek8evZs2cDhWcnzZw5k27dujX5We+88079n1tvvfUK1b3uuusu9bpuGKfx8bo5OXXnzzzzTFZeeWVuueUWfvjDH9KrVy8OOeQQfvrTn9KnT5/6GgcOHNjsZ8+fP3+Zz2nqs+os7741lqWGcjCstGNXT34lc9vjd92ojJVIUvmtt956HHfccZx66qm8/PLLjBgxov7cW2+9xec+97mlXgMMGDAAgN69ezN48GBuv/32Jq9dN0m2T58+zf6izqrx1vJrr702AHPmzGHIkCH1x+fMmVNfG0C3bt0YN24c48aNY86cOfz+97/nu9/9LgsXLuQ3v/kNffr0AQpBYtNNN23ys9dee21efPHFZY43/qw6y7tvjTWsoZIcBpIk5c7rr7/e5PEXXngBYJmVQo1DyG233UaXLl3qA83o0aN5/fXX6dWrF8OHD1/mq+6X8KhRo3jiiSf429/+1mxtPXr0WGalUUt22223+poa+tWvfgVQ33PU0DrrrMNxxx3HXnvtxTPPPAMU5oV06dKF2traFj9r1qxZ/OlPf1rq+K233kq/fv3YfPPNlzq+vPvW2NChQxk0aBDXXHMNKaVm6yg1e1Y6gAEjj2rx/OyHbqpQJZJUGltuuSV77LEHX/7ylxk8eDDvvfceEydO5KqrruLQQw9lgw02WKr9xIkT+a//+q/6sDFhwgSOOuqo+kmiX//617n++usZOXIk3/ve99h66635+OOP+ec//8k999zD7373O1ZZZRVOO+00br31Vvbaay/Gjx/PVlttxdtvv83dd9/NVVddxWqrrcYWW2zB/Pnz+cUvfsHw4cNZeeWV2WqrrZr9WT73uc9x+OGHU1NTw+LFi9lpp52YMmUK5513HocffjjDhg0DYMyYMWy99dZst912rLXWWvzlL3/hvvvu44QTTgBgyJAh9ZNrFyxYwIEHHkjXrl154okn2GyzzTjssMM4+uijufzyyzn44IO54IILGDhwIL/61a944IEH+OUvf7nU5Nos962xiOCyyy7j4IMPZs899+TEE0+kb9++PP/888ydO5cJEya0+e+8JYYVSerAVmS7+2q68MILmThxIj/4wQ9466236Nq1K0OHDuXHP/4x3/nOd5Zpf8stt3DxxRfzi1/8gu7du3P88cfXr3KBwhDL/fffz49//GNqa2t59dVXWXXVVRkyZAj7778/3bt3B2DNNdfkT3/6E+PHj+fHP/4x77zzDv3792fPPfesb3PccccxdepUzjzzTN5991023HBDZsyY0eLPU7cM+7rrruP8889nvfXWY9y4cZxzzjn1bXbddVfuuOMOrrjiChYuXMgGG2zA6aefzllnnVXf5qKLLmLjjTfmyiuv5MYbb2TVVVdl2LBh9SukVl11VR599FFOP/10zjjjDBYsWMCmm27KzTffvMwE3yz3rSljxozhgQce4LzzzuPYY48FCkGqqb+XUolKduOU0vDhw9O0adOqXUbV1NTU1M9ZydKzUjdnxQm2Usf0/PPPL9PF3xnccMMNHHPMMbz88stsvPHG1S6n3ajGfVvef6MR8VRKaXhT55yzIkmScs2wIkmScs2wIklqt44++mhSSg4BtVJ7u2+GFUmSlGuGFUmSlGuGFUmSlGuGFUmSlGuGFUmSlGuGFUmSlGuGFUmSlGs+G0iSOrL/Pba6n3/ItW1+a92W8HV69erFRhttxPHHH8+JJ57ISiutxKBBg9h555255ZZbSlEtNTU17Lrrruy5554luV45TJo0iUmTJvGDH/yALl2y9TnU3ctXX32VQYMGlbfAMrBnRZKUa3fccQdTpkzht7/9LSNGjOCUU07h3HPPLctnTZgwgYcffrgs1y6VSZMmMWHCBJYsWZL5Pfvvvz9Tpkxh3XXXLWNl5WPPiiQp17bZZpv6nVZHjRrF9OnTueyyy8oWWDqSTz75hJVWWom+ffvSt2/fapfTZvasSJLale23354FCxYwd+7c+mO33XYbm2++OauuuirDhw/nscceW+Z9t9xyC1tvvTUrr7wyffr04cgjj+TNN9+sPx8RAFxwwQVEBBGx1JPql/d+gEGDBnHEEUdw8803s+mmm9KzZ0922WUXXn75ZT744ANOOOEEevfuTf/+/fne977H4sWLl3r/22+/zUknncSAAQPo0aMHm222GbW1tfXna2pqmDBhAgDdunWrrxNgxowZRARXXnklp59+Ouuttx49evTg3Xff5YYbbiAimDFjxlKfd/XVV7PddtvRs2dP1lprLXbbbTcef/zxVvxtVIY9K5KkduXVV1+la9eu9OrVC4A//vGPvPjii5x33nmsvPLKnH322RxwwAHMmDGDNddcE4Da2lpOOOEEDjvsMH70ox/xxhtvcOaZZ/LnP/+Zp59+ml69ejFlyhR23HFHjj76aE444QQABg4cmPn9dSZPnsw///lPLrzwQj7++GO+853v8JWvfIWNNtqIjTfemNtuu43Jkydz/vnnM2TIEE4++WQA3nvvPb74xS+yaNEiampqGDx4MPfffz8nnXQSH330EaeccgrHHXccs2bN4tprr+Wxxx6ja9euy9yfCy64gO23357a2lo+/fRTVl555Sbv4/e//30uvvhijj32WCZMmECXLl2YOnUqr732GjvttFPJ/r5KwbAiScq1Tz/9lMWLF7NgwQJuv/127rzzTr70pS+xyiqrAIVf8n/9619Za621AFhnnXXYfvvtmThxIl/72tf49NNPOfvss9l999257bbb6q+72Wabscsuu3Ddddfx7W9/my984QsADBgwoP77us/P8v4677//Pvfddx9rrLEGAHPmzOHUU09lxIgRXHTRRQDsvffe3Hvvvdxxxx31YeXyyy9n5syZ/OMf/2CTTTYBYK+99uLdd99lwoQJnHTSSQwcOLA+QO2www6stNKyv8b79+/PXXfdVd/j0pTp06dz6aWXctppp3HJJZfUH99///2X+/dRDQ4DSZJybbPNNqNbt26svfbanHzyyXz961/nuuuuqz+/44471gcVgK222gqA1157DYAXX3yRuXPn8vWvf32p6+68885suOGGPProoy1+fmvfv+OOO9YHlbr6AfbZZ59lfq7XX3+9/vV9993HDjvswODBg1m8eHH91z777MM777zDc88912KddQ466KAWgwrAgw8+yJIlSxg7dmyma1abPSuSpFy76667GDhwIKutthobbrjhMsMaa6+99lKve/ToAcCHH34IwPz58wGaXAmzzjrr1J9vTmvf3zA4AXTv3r3Z43U1AsydO5fp06fTrVu3Jut45513WqyzTpYVP3XXquulyTvDiiQp17bccsv61UBtURdm5syZs8y5OXPmMHz48LK+P6vevXvTr18/Lr/8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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "# Plot it; here's mine!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Do the differences between the two distributions make sense? Why or why not?**" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# answer here" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Problem 3\n", "\n", "The [UVJ diagram](https://iopscience.iop.org/article/10.3847/2041-8213/ab2f8c/pdf) is a useful diagnostic tool in extragalactic astronomy which allows one to relatively accurately diagnose a galaxy as star forming or quiescent, even in the presence of dust. You can read more at the link if you're unfamiliar. It is composed by plotting the \"U-V\" color of the galaxy against the \"V-J\" colors. You'll likely know U and V (these are from the Johnsons-Cousin's filter system). J is a filter in the near infrared. \n", "\n", "In this problem, we're going to write a function that can create a UVJ diagram for subsets of our data, cutting on mass and redshift. \n", "\n", "You'll need to access the following columns in the data (besides redshift, which you've already handled):\n", "\n", "- stellar mass: the mass of all the stars in the galaxy. (column: `lmass`, flagged value of -1)\n", "- star formation rate: rate at which galaxy is forming stars. (column: `lsfr`, flagged value of -99.0)\n", "- U band flux density (column: `l153`, flagged value of -99.0)\n", "- V band flux density (column: `l155`, flagged value of -99.0)\n", "- J band flux density (column: `l161`, flagged value of -99.0)\n", "\n", "### Problem 3.1 \n", "\n", "For step one, we need to be able to filter our dataframe for particular mass and redshift ranges. \n", "\n", "Write a function, `select_galaxies()`, which takes as arguments `M, delta_M, z, delta_z` (and our dataframe). \n", "It should then return a df of only systems between M-deltaM to M+deltaM, and z-deltaz to z+deltaz. The columns it should return are the ones specified above, plus 'z'.\n", "\n", "There is actually a column in `rf_df` called `z`, that contains the spec_z if available or the peak z if not. At the time of writing, I cannot determine why this column was not included in the merge. In any case, set `df['z']` equal to `rf_df.z` before continuing, as you'll use it below.\n", "\n", "\n", "```{note}\n", "All masses and sfrs are in log units. \n", "```\n", "\n", "Try your function out using a mass of 10, delta M of 0.5 (i.e., a bin from 9.5 - 10.5), a redshift of 1, and a delta z of 0.25." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Add rf_df.z to the dataframe df " ] }, { "cell_type": "code", "execution_count": 262, "metadata": {}, "outputs": [], "source": [ "# Define your select galaxies function \n" ] }, { "cell_type": "code", "execution_count": 261, "metadata": {}, "outputs": [], "source": [ "# Here's the output for the provided example \n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Problem 3.2\n", "\n", "Great, we can now get subsamples in mass/redshift bins. This is important because the UVJ diagram actually changes as a function of mass and redshift. \n", "\n", "Next we need to get the colors out. Write a function `get_colors()` which takes the same arguments as your `select_galaxies()` function above. Inside, it should run `select_galaxies` passing through the arguments, and then from the resulting data frame, calculate U-V and U-J (see below). Add these as columns to said dataframe with names 'U-V' and 'V-J' and return it. \n", "\n", "Run this function with the same mass/redshift bin from above and look at it.\n", "\n", "```{warning}\n", "As noted above, the U,V, and J band data are in Fnu (flux densities). Thus, a color is computed via -2.5*log10(Lfilter1/Lfilter2)\n", "```\n" ] }, { "cell_type": "code", "execution_count": 263, "metadata": {}, "outputs": [], "source": [ "#Define get colors " ] }, { "cell_type": "code", "execution_count": 264, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
zlmasslsfrl153l155l161U-VV-J
id
440.684029.89-1.283.7673914.4356046.52131.4584861.270543
920.694269.76-0.038.0849721.0779048.39691.0403720.902476
1780.9479010.36-1.901.947218.6058549.25091.6134521.894051
1940.6507010.120.3313.2522042.32950112.53401.2608881.061602
2360.5325710.35-0.748.3177342.76950111.60201.7778231.041345
...........................
497020.531809.970.3641.6611091.52100200.92200.8544750.853767
500000.835359.840.239.2587221.8622052.29720.9328570.946961
503990.6805710.46-10.146.0863038.30250119.64301.9971841.236650
504940.711509.59-0.7113.1736025.5752041.64130.7202860.529263
505000.579829.79-1.3810.9939029.3991067.92421.0679560.909226
\n", "

669 rows × 8 columns

\n", "
" ], "text/plain": [ " z lmass lsfr l153 l155 l161 U-V V-J\n", "id \n", "44 0.68402 9.89 -1.28 3.76739 14.43560 46.5213 1.458486 1.270543\n", "92 0.69426 9.76 -0.03 8.08497 21.07790 48.3969 1.040372 0.902476\n", "178 0.94790 10.36 -1.90 1.94721 8.60585 49.2509 1.613452 1.894051\n", "194 0.65070 10.12 0.33 13.25220 42.32950 112.5340 1.260888 1.061602\n", "236 0.53257 10.35 -0.74 8.31773 42.76950 111.6020 1.777823 1.041345\n", "... ... ... ... ... ... ... ... ...\n", "49702 0.53180 9.97 0.36 41.66110 91.52100 200.9220 0.854475 0.853767\n", "50000 0.83535 9.84 0.23 9.25872 21.86220 52.2972 0.932857 0.946961\n", "50399 0.68057 10.46 -10.14 6.08630 38.30250 119.6430 1.997184 1.236650\n", "50494 0.71150 9.59 -0.71 13.17360 25.57520 41.6413 0.720286 0.529263\n", "50500 0.57982 9.79 -1.38 10.99390 29.39910 67.9242 1.067956 0.909226\n", "\n", "[669 rows x 8 columns]" ] }, "execution_count": 264, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#Here's the output you're looking for. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Problem 3.3 \n", "\n", "Now that we can easily grab U-V and V-J colors for subsamples, we're ready to plot! \n", "\n", "Next, set your xlim and ylim to (0,2) in V-J (x axis) and (0,2.8) in U-V (y axis).\n", "\n", "Once you have the distribution plotted nicely, use the definitions of the bounding box provided in [Whitaker et al. 2011](https://iopscience.iop.org/article/10.1088/0004-637X/735/2/86/pdf) (Eqns 15, Fig 17 for example) to draw the box where quiescent galaxies sit. \n", "\n", "Finally, let's add the galaxies. For this example, use a log mass of 9.5 with a delta M of 2 (so, galaxies from $10^{7.5}$ $M_{\\odot}$ to $10^{11.5}$ $M_{\\odot}$), in the redshift range of 0.5 to 1.5. Can you identify the quiescent sequence?\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Bonus (+2) \n", "\n", "(+1) Now that you can easily plot up a UVJ diagram for a given mass/redshift bin, make a plot with 6 panels. Across the 3, plot the UVJ diagram in the redshift bins 0-0.5, 0.5-1.0, 1.0-2.0. In the top panel, include galaxies in the mass range 8-9.5, and in the bottom, 9.5-11. \n", "\n", "(+1) Feeling extra fancy? Use the conditions on the UVJ quiescent box to color the quiescent galaxies red and the star forming galaxies blue in you plots. \n", "\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Wrap Up\n", "\n", "We've barely scratched the surface for what we can do with `pandas`, but we hope that if you're planning to work with \"large\" amounts of data (say, 200 columns and 500,000 rows), then pandas is a great tool for working with them. " ] } ], "metadata": { "kernelspec": { "display_name": "a330", "language": "python", "name": "a330" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.11" } }, "nbformat": 4, "nbformat_minor": 4 }