{"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"name":"2020-11-03 - lesson #9 notebook.ipynb","provenance":[],"collapsed_sections":["Jy_ZjZTTYTqY","PsLWyh4SNJBC"]},"kernelspec":{"name":"python3","display_name":"Python 3"}},"cells":[{"cell_type":"markdown","metadata":{"id":"n-tRl-ouYOAe"},"source":["# Video lesson \\#9 notebook"]},{"cell_type":"markdown","metadata":{"id":"Jy_ZjZTTYTqY"},"source":["## Part 1: Pandas `Series` and `DataFrame` objects"]},{"cell_type":"code","metadata":{"id":"57m7NRAMYSyB"},"source":["# Import Pandas (and NumPy, because Pandas is built on NumPy)\n","import numpy as np\n","import pandas as pd"],"execution_count":null,"outputs":[]},{"cell_type":"code","metadata":{"id":"U5tMy1iIBhXl","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1604344345789,"user_tz":480,"elapsed":950,"user":{"displayName":"Ethan C Campbell","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GjCBYTiuomqOsCakND1k_5wj0kYvFY53Jt7kunt=s64","userId":"11255944928409084259"}},"outputId":"d793df50-a15b-415c-b210-c80414210ba6"},"source":["# Create two new Pandas Series objects\n","s1 = pd.Series(index=[2016,2017,2018,2019,2020],\n"," data=[4.1,5.2,6.3,7.4,8.5],\n"," name='Temperature')\n","s2 = pd.Series(index=[2016,2017,2018,2019,2020],\n"," data=[35.5,35.0,34.5,34.0,33.5],\n"," name='Salinity')\n","\n","# Series still have a length, as with lists and NumPy arrays\n","print(len(s1))"],"execution_count":null,"outputs":[{"output_type":"stream","text":["5\n"],"name":"stdout"}]},{"cell_type":"code","metadata":{"id":"4u-PfDtSBjKz","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1604344345790,"user_tz":480,"elapsed":932,"user":{"displayName":"Ethan C Campbell","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GjCBYTiuomqOsCakND1k_5wj0kYvFY53Jt7kunt=s64","userId":"11255944928409084259"}},"outputId":"b78567c5-fbe6-4715-9da1-8722d06424cb"},"source":["# Extract parts of the Series object\n","print(s1.index) # get index as Index object (not very useful)\n","print(s1.index.values) # get index converted into NumPy array\n","print(s1.values) # get data converted into NumPy array"],"execution_count":null,"outputs":[{"output_type":"stream","text":["Int64Index([2016, 2017, 2018, 2019, 2020], dtype='int64')\n","[2016 2017 2018 2019 2020]\n","[4.1 5.2 6.3 7.4 8.5]\n"],"name":"stdout"}]},{"cell_type":"code","metadata":{"id":"iQ6_4IOOESJJ","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1604344345790,"user_tz":480,"elapsed":913,"user":{"displayName":"Ethan C Campbell","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GjCBYTiuomqOsCakND1k_5wj0kYvFY53Jt7kunt=s64","userId":"11255944928409084259"}},"outputId":"101d87ac-1aa5-4cb7-96e5-15c5e097fb90"},"source":["# Select data from Series object using .iloc (Python/NumPy-style selection by position)\n","print('\\nOption 1:\\n', s1.iloc[3]) # use a single integer index (returns the value)\n","print('\\nOption 2:\\n', s1.iloc[[2,3,4]]) # use a list or array of integer indices (returns a Series)\n","print('\\nOption 3:\\n', s1.iloc[2:5]) # use a slice of integer indices (returns a Series)\n","print('\\nOption 4:\\n', s1.iloc[[False,False,True,True,True]]) # use a Boolean array (returns a Series)\n","\n","# Select data from Series object using .loc (selection by label)\n","print('\\nOption 5:\\n', s1.loc[2019]) # use a single label of the index (NOT an integer position along the index)\n","print('\\nOption 6:\\n', s1.loc[[2018,2019,2020]]) # use a list or array of labels\n","print('\\nOption 7:\\n', s1.loc[2018:2020]) # use a slice of labels (UNLIKE standard Python/NumPy slices, the end value is inclusive)\n","\n","# Remember that you have to use .values to convert a Series to a NumPy array:\n","print('\\nReminder:\\n', s1.loc[2018:2020].values)"],"execution_count":null,"outputs":[{"output_type":"stream","text":["\n","Option 1:\n"," 7.4\n","\n","Option 2:\n"," 2018 6.3\n","2019 7.4\n","2020 8.5\n","Name: Temperature, dtype: float64\n","\n","Option 3:\n"," 2018 6.3\n","2019 7.4\n","2020 8.5\n","Name: Temperature, dtype: float64\n","\n","Option 4:\n"," 2018 6.3\n","2019 7.4\n","2020 8.5\n","Name: Temperature, dtype: float64\n","\n","Option 5:\n"," 7.4\n","\n","Option 6:\n"," 2018 6.3\n","2019 7.4\n","2020 8.5\n","Name: Temperature, dtype: float64\n","\n","Option 7:\n"," 2018 6.3\n","2019 7.4\n","2020 8.5\n","Name: Temperature, dtype: float64\n","\n","Reminder:\n"," [6.3 7.4 8.5]\n"],"name":"stdout"}]},{"cell_type":"code","metadata":{"id":"vaVz5ACPFbLX","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1604344345791,"user_tz":480,"elapsed":895,"user":{"displayName":"Ethan C Campbell","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GjCBYTiuomqOsCakND1k_5wj0kYvFY53Jt7kunt=s64","userId":"11255944928409084259"}},"outputId":"3ba0d7ed-4cfa-4904-c00e-8f4813bd4a30"},"source":["# Changing values of a Series using the indexing options above\n","s1.loc[2018] = 5.3\n","print(s1)\n","s1.iloc[3:5] = [6.4,7.5]\n","print(s1)\n","s1.loc[2018:2020] += 1\n","print(s1)"],"execution_count":null,"outputs":[{"output_type":"stream","text":["2016 4.1\n","2017 5.2\n","2018 5.3\n","2019 7.4\n","2020 8.5\n","Name: Temperature, dtype: float64\n","2016 4.1\n","2017 5.2\n","2018 5.3\n","2019 6.4\n","2020 7.5\n","Name: Temperature, dtype: float64\n","2016 4.1\n","2017 5.2\n","2018 6.3\n","2019 7.4\n","2020 8.5\n","Name: Temperature, dtype: float64\n"],"name":"stdout"}]},{"cell_type":"code","metadata":{"id":"qCFOAtW1NvJO","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1604344345791,"user_tz":480,"elapsed":879,"user":{"displayName":"Ethan C Campbell","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GjCBYTiuomqOsCakND1k_5wj0kYvFY53Jt7kunt=s64","userId":"11255944928409084259"}},"outputId":"f0999ff5-e085-468c-9de2-759fbd48bf9c"},"source":["# Add a new value to a Series using a new index label\n","s1.loc[2021] = 9.6\n","print(s1)"],"execution_count":null,"outputs":[{"output_type":"stream","text":["2016 4.1\n","2017 5.2\n","2018 6.3\n","2019 7.4\n","2020 8.5\n","2021 9.6\n","Name: Temperature, dtype: float64\n"],"name":"stdout"}]},{"cell_type":"code","metadata":{"id":"WlIVNZ5FQyGB"},"source":["# Two ways of creating a Pandas DataFrame object\n","\n","# Option 1: join two or more Series objects\n","df = pd.concat([s1,s2],axis=1)\n","\n","# Option 2: provide a dictionary with the data lists or NumPy arrays\n","df = pd.DataFrame(index=[2016,2017,2018,2019,2020],\n"," data={'Temperature':[4.1,5.2,6.3,7.4,8.5],\n"," 'Salinity':[35.5,35.0,34.5,34.0,33.5]})"],"execution_count":null,"outputs":[]},{"cell_type":"code","metadata":{"id":"ejAFmOmzRGuW","colab":{"base_uri":"https://localhost:8080/","height":648},"executionInfo":{"status":"ok","timestamp":1604344346133,"user_tz":480,"elapsed":1199,"user":{"displayName":"Ethan C Campbell","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GjCBYTiuomqOsCakND1k_5wj0kYvFY53Jt7kunt=s64","userId":"11255944928409084259"}},"outputId":"a20051c6-69c8-4850-9116-ddf7915103fb"},"source":["# Get information about the DataFrame object\n","print(df.shape) # get dimensions\n","print(df.size) # get number of data values\n","print(df) # print() still works, but is not as nice looking as display()\n","display(df) # display() opens the display interface, a more nicely formatted view of the object\n","df.describe() # get useful summary statistics"],"execution_count":null,"outputs":[{"output_type":"stream","text":["(5, 2)\n","10\n"," Temperature Salinity\n","2016 4.1 35.5\n","2017 5.2 35.0\n","2018 6.3 34.5\n","2019 7.4 34.0\n","2020 8.5 33.5\n"],"name":"stdout"},{"output_type":"display_data","data":{"text/html":["
"],"text/plain":[" Temperature Salinity\n","count 5.000000 5.000000\n","mean 6.300000 34.500000\n","std 1.739253 0.790569\n","min 4.100000 33.500000\n","25% 5.200000 34.000000\n","50% 6.300000 34.500000\n","75% 7.400000 35.000000\n","max 8.500000 35.500000"]},"metadata":{"tags":[]},"execution_count":43}]},{"cell_type":"code","metadata":{"id":"4dRFCmGNUhLW","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1604344346133,"user_tz":480,"elapsed":1180,"user":{"displayName":"Ethan C Campbell","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GjCBYTiuomqOsCakND1k_5wj0kYvFY53Jt7kunt=s64","userId":"11255944928409084259"}},"outputId":"d03071d5-ab41-44ee-bfc8-f665b5030530"},"source":["# Extract parts of the DataFrame object\n","print(df.index.values) # get index as a NumPy array\n","print(df.columns.values) # get column names as a NumPy array\n","print(df.values) # get data as a NumPy array\n","print(df['Salinity'].values) # get one column as a NumPy array\n"," # (similar to dictionary indexing)"],"execution_count":null,"outputs":[{"output_type":"stream","text":["[2016 2017 2018 2019 2020]\n","['Temperature' 'Salinity']\n","[[ 4.1 35.5]\n"," [ 5.2 35. ]\n"," [ 6.3 34.5]\n"," [ 7.4 34. ]\n"," [ 8.5 33.5]]\n","[35.5 35. 34.5 34. 33.5]\n"],"name":"stdout"}]},{"cell_type":"code","metadata":{"id":"cS0qFEqydUnc","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1604344346134,"user_tz":480,"elapsed":1163,"user":{"displayName":"Ethan C Campbell","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GjCBYTiuomqOsCakND1k_5wj0kYvFY53Jt7kunt=s64","userId":"11255944928409084259"}},"outputId":"b1a4b00e-e10f-4a2a-91d2-e248bfcbc1a5"},"source":["# Select data from Series object using .iloc or .loc\n","print('\\nExample 1:\\n', df.iloc[3]) # use a single index (returns a Series)\n","print('\\nExample 2:\\n', df.loc[2019]) # use a single label (returns a Series)\n","print('\\nExample 3:\\n', df.iloc[2:5]) # use a slice of integer indices (returns a DataFrame)\n","print('\\nExample 4:\\n', df.loc[2018:2020]) # use a slice of labels (returns a DataFrame)\n","print('\\nExample 5:\\n', df['Temperature'].loc[2019]) # select a column AND choose a single row (returns the value)\n","print('\\nExample 6:\\n', df[['Temperature','Salinity']].loc[2019]) # select multiple columns AND choose a single row (returns a Series)\n","print('\\nExample 7:\\n', df[df['Temperature'] > 6.0]) # use a Boolean condition applied to one column (returns a DataFrame)\n","\n","# NOTE: changing values using .iloc and .loc selection works similar to as shown above with Series"],"execution_count":null,"outputs":[{"output_type":"stream","text":["\n","Example 1:\n"," Temperature 7.4\n","Salinity 34.0\n","Name: 2019, dtype: float64\n","\n","Example 2:\n"," Temperature 7.4\n","Salinity 34.0\n","Name: 2019, dtype: float64\n","\n","Example 3:\n"," Temperature Salinity\n","2018 6.3 34.5\n","2019 7.4 34.0\n","2020 8.5 33.5\n","\n","Example 4:\n"," Temperature Salinity\n","2018 6.3 34.5\n","2019 7.4 34.0\n","2020 8.5 33.5\n","\n","Example 5:\n"," 7.4\n","\n","Example 6:\n"," Temperature 7.4\n","Salinity 34.0\n","Name: 2019, dtype: float64\n","\n","Example 7:\n"," Temperature Salinity\n","2018 6.3 34.5\n","2019 7.4 34.0\n","2020 8.5 33.5\n"],"name":"stdout"}]},{"cell_type":"code","metadata":{"id":"NOZf4kXThUQ7","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1604344346134,"user_tz":480,"elapsed":1145,"user":{"displayName":"Ethan C Campbell","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GjCBYTiuomqOsCakND1k_5wj0kYvFY53Jt7kunt=s64","userId":"11255944928409084259"}},"outputId":"81991544-e5ed-4f3e-fae7-9c965e9ee977"},"source":["# Apply NumPy functions to Series and DataFrame objects\n","print('\\nExample 1:\\n', df.mean()) # take the mean along the index (axis 0)\n","print('\\nExample 2:\\n', df.mean(axis=0)) # same as above\n","print('\\nExample 3:\\n', df.mean(axis=1)) # take the mean along the columns (axis 1)\n","print('\\nExample 4:\\n', df.mean(skipna=True)) # ignore NaN values (if present) when taking the mean\n","\n","# Combine column extraction, selection by label, and applying a NumPy function\n","print('\\nExample 5:\\n', df['Salinity'].loc[2017:].mean()) # returns a single value"],"execution_count":null,"outputs":[{"output_type":"stream","text":["\n","Example 1:\n"," Temperature 6.3\n","Salinity 34.5\n","dtype: float64\n","\n","Example 2:\n"," Temperature 6.3\n","Salinity 34.5\n","dtype: float64\n","\n","Example 3:\n"," 2016 19.8\n","2017 20.1\n","2018 20.4\n","2019 20.7\n","2020 21.0\n","dtype: float64\n","\n","Example 4:\n"," Temperature 6.3\n","Salinity 34.5\n","dtype: float64\n","\n","Example 5:\n"," 34.25\n"],"name":"stdout"}]},{"cell_type":"code","metadata":{"id":"eNzNLSyGkaHc"},"source":["# Save a Pandas DataFrame as a CSV file\n","# df.to_csv('filepath/including/filename.csv')\n","\n","# Read a CSV file as a Pandas DataFrame (more powerful than np.genfromtxt()!)\n","# See available arguments: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_csv.html\n","# df = pd.read_csv('filepath/including/filename.csv',delimiter=',',delim_whitespace=False,header=0)\n","\n","# Read an Excel spreadsheet as a Pandas DataFrame\n","# See available arguments: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_excel.html\n","# df = pd.read_excel('filepath/including/filename.xlsx',sheet_name='Sheet1')"],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"PsLWyh4SNJBC"},"source":["## Part 2: xarray `DataArray` and `Dataset` objects"]},{"cell_type":"code","metadata":{"id":"nKguR6pRYCBN"},"source":["# Import xarray (and other libraries, because they are helpful when working with xarray files)\n","import numpy as np\n","import pandas as pd\n","import xarray as xr\n","from datetime import datetime, timedelta\n","import matplotlib.pyplot as plt"],"execution_count":null,"outputs":[]},{"cell_type":"code","metadata":{"id":"GqgHqCLUYaTz"},"source":["# You'll need to install the netCDF4 library to work with netCDF files\n","# You should only need to run this line of code once per Colab notebook,\n","# so comment it out or delete it afterwards\n","# !pip install netcdf4"],"execution_count":null,"outputs":[]},{"cell_type":"code","metadata":{"id":"GpTSfp17Ybq3","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1604344346136,"user_tz":480,"elapsed":1103,"user":{"displayName":"Ethan C Campbell","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GjCBYTiuomqOsCakND1k_5wj0kYvFY53Jt7kunt=s64","userId":"11255944928409084259"}},"outputId":"2706a539-4a70-4716-8dbd-e45b55425bf3"},"source":["# Give Colab access to Google Drive\n","from google.colab import drive\n","drive.mount('/content/drive')"],"execution_count":null,"outputs":[{"output_type":"stream","text":["Drive already mounted at /content/drive; to attempt to forcibly remount, call drive.mount(\"/content/drive\", force_remount=True).\n"],"name":"stdout"}]},{"cell_type":"code","metadata":{"id":"aeJNHWpzYe5B"},"source":["# NOTE: you'll need to change this variable to match your own filepath\n","filepath = 'drive/My Drive/OCEAN 215 - Autumn \\'20/OCEAN 215 - Autumn \\'20 - Course documents/' \\\n"," + 'Video lesson slides and notebooks/2020-11-03 - lesson #9 data/bsose_monthly_velocities.nc'\n","\n","# This is how we load a netCDF file\n","# (This method is safe on Colab for files\n","# up to about 0.5 GB [500 MB] in size)\n","data = xr.open_dataset(filepath)"],"execution_count":null,"outputs":[]},{"cell_type":"code","metadata":{"id":"P03-CHg_ZlZ4","colab":{"base_uri":"https://localhost:8080/","height":383},"executionInfo":{"status":"ok","timestamp":1604344346137,"user_tz":480,"elapsed":1076,"user":{"displayName":"Ethan C Campbell","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GjCBYTiuomqOsCakND1k_5wj0kYvFY53Jt7kunt=s64","userId":"11255944928409084259"}},"outputId":"58ea80a2-46c2-42f5-f8f0-0022dc43e671"},"source":["# Examine structure of xarray Dataset using the interactive display() interface\n","display(data) # Note there are 2 variables (eastward velocities, northward velocities)\n"," # 4 dimensions, and 4 coordinates (time, lat, lon, depth), so each variable is a 4D array\n","\n","# Note that you can click the buttons to view attributes (page icon) and actual data values (cylinder icon)"],"execution_count":null,"outputs":[{"output_type":"display_data","data":{"text/html":["
"],"text/plain":["\n","[49533120 values with dtype=float32]\n","Coordinates:\n"," * time (time) datetime64[ns] 2012-01-30T20:00:00 ... 2012-12-30T12:00:00\n"," * lat (lat) float32 -77.96525 -77.89555 ... -30.089203 -29.789328\n"," * lon (lon) float32 -179.66667 -179.33333 -179.0 ... 179.66667 180.0\n"," * depth (depth) float32 2.1 26.25 65.0 105.0 ... 1800.0 3000.0 4600.0\n","Attributes:\n"," units: m/s\n"," long_name: Zonal Component of Velocity (m/s)\n"," standard_name: UVEL\n"," mate: VVEL"]},"metadata":{"tags":[]}}]},{"cell_type":"code","metadata":{"id":"6ToFSWx56PvG","colab":{"base_uri":"https://localhost:8080/","height":237},"executionInfo":{"status":"ok","timestamp":1604344347103,"user_tz":480,"elapsed":2000,"user":{"displayName":"Ethan C Campbell","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GjCBYTiuomqOsCakND1k_5wj0kYvFY53Jt7kunt=s64","userId":"11255944928409084259"}},"outputId":"eb982b77-dc11-416f-e217-fd9d6e6a103d"},"source":["# You can do mathematical calculations between xarray DataArrays, as long as their dimensions match\n","\n","# Example: calculate current speed using Pythagorean theorem: \n","# speed = sqrt(U^2 + V^2)\n","speed = (data['U']**2 + data['V']**2)**0.5\n","display(speed)\n","\n","# Note that the coordinates and dimensions remained the same:"],"execution_count":null,"outputs":[{"output_type":"display_data","data":{"text/html":["
"],"text/plain":["\n","array(0.12589, dtype=float32)\n","Coordinates:\n"," time datetime64[ns] 2012-01-30T20:00:00\n"," lat float32 -52.70605\n"," lon float32 -13.0\n"," depth float32 2.1\n","Attributes:\n"," units: meters/second\n"," long_name: Zonal Component of Velocity (m/s)\n"," standard_name: UVEL\n"," mate: VVEL"]},"metadata":{"tags":[]},"execution_count":57}]},{"cell_type":"code","metadata":{"id":"uNihw6GC_Tay","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1604344347105,"user_tz":480,"elapsed":1912,"user":{"displayName":"Ethan C Campbell","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GjCBYTiuomqOsCakND1k_5wj0kYvFY53Jt7kunt=s64","userId":"11255944928409084259"}},"outputId":"23e3a63a-0e55-43ec-c052-16b0d6ed7fcb"},"source":["# You can convert a single-value Dataset result to a number using float() or .item():\n","print(data['U'].isel(time=0,lat=200,lon=500,depth=0).item())\n","print(float(data['U'].isel(time=0,lat=200,lon=500,depth=0)))"],"execution_count":null,"outputs":[{"output_type":"stream","text":["0.1258898824453354\n","0.1258898824453354\n"],"name":"stdout"}]},{"cell_type":"code","metadata":{"id":"qBfXHrsHEwtp","colab":{"base_uri":"https://localhost:8080/","height":306},"executionInfo":{"status":"ok","timestamp":1604344347106,"user_tz":480,"elapsed":1889,"user":{"displayName":"Ethan C Campbell","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GjCBYTiuomqOsCakND1k_5wj0kYvFY53Jt7kunt=s64","userId":"11255944928409084259"}},"outputId":"c6cf5f4c-31d6-4325-bf01-1d16579bad77"},"source":["# You can select multiple indices using .isel()\n","data['U'].isel(time=0,lat=200,lon=500,depth=[0,1,2,3,4]) # analogous to NumPy: u[0,0,0,[0,1,2,3,4]]\n","data['U'].isel(time=0,lat=200,lon=500,depth=slice(0,5)) # analogous to NumPy: u[0,0,0,0:5]\n","\n","# Notice below that the result has a dimension of 5 depths, and we see the depths range from 2.1 m to 146.5 m:"],"execution_count":null,"outputs":[{"output_type":"execute_result","data":{"text/html":["
"],"text/plain":["\n","array([0.12589 , 0.050398, 0.057173, 0.061555, 0.057382], dtype=float32)\n","Coordinates:\n"," time datetime64[ns] 2012-01-30T20:00:00\n"," lat float32 -52.70605\n"," lon float32 -13.0\n"," * depth (depth) float32 2.1 26.25 65.0 105.0 146.5\n","Attributes:\n"," units: meters/second\n"," long_name: Zonal Component of Velocity (m/s)\n"," standard_name: UVEL\n"," mate: VVEL"]},"metadata":{"tags":[]},"execution_count":59}]},{"cell_type":"code","metadata":{"id":"So5WL2P5Gmck","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1604344347106,"user_tz":480,"elapsed":1866,"user":{"displayName":"Ethan C Campbell","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GjCBYTiuomqOsCakND1k_5wj0kYvFY53Jt7kunt=s64","userId":"11255944928409084259"}},"outputId":"72a6667a-eae3-4949-92ae-84dae6a0a13b"},"source":["# Multiple results can be converted from a Dataset to the underlying NumPy array using .values:\n","data['U'].isel(time=0,lat=200,lon=500,depth=slice(0,5)).values"],"execution_count":null,"outputs":[{"output_type":"execute_result","data":{"text/plain":["array([0.12588988, 0.05039841, 0.05717332, 0.06155456, 0.057382 ],\n"," dtype=float32)"]},"metadata":{"tags":[]},"execution_count":60}]},{"cell_type":"code","metadata":{"id":"0Whazqb_JA-y","colab":{"base_uri":"https://localhost:8080/","height":376},"executionInfo":{"status":"ok","timestamp":1604344369036,"user_tz":480,"elapsed":295,"user":{"displayName":"Ethan C Campbell","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GjCBYTiuomqOsCakND1k_5wj0kYvFY53Jt7kunt=s64","userId":"11255944928409084259"}},"outputId":"d66a1831-107e-4f53-d711-b8a6072578f0"},"source":["# This also works when the underlying NumPy array has more than one dimension (e.g. is 2-D, 3-D, etc.):\n","display(data['U'].isel(time=0,lat=slice(200,204),lon=slice(500,504),depth=0))\n","data['U'].isel(time=0,lat=slice(200,204),lon=slice(500,504),depth=0).values\n","\n","# Calling .values on the result gave a 4x4 NumPy array:"],"execution_count":null,"outputs":[{"output_type":"display_data","data":{"text/html":["
"],"text/plain":["\n","array(0.12589, dtype=float32)\n","Coordinates:\n"," time datetime64[ns] 2012-01-30T20:00:00\n"," lat float32 -52.70605\n"," lon float32 -13.0\n"," depth float32 2.1\n","Attributes:\n"," units: meters/second\n"," long_name: Zonal Component of Velocity (m/s)\n"," standard_name: UVEL\n"," mate: VVEL"]},"metadata":{"tags":[]},"execution_count":62}]},{"cell_type":"code","metadata":{"id":"_hfDPUWFYaBC","colab":{"base_uri":"https://localhost:8080/","height":306},"executionInfo":{"status":"ok","timestamp":1604344913343,"user_tz":480,"elapsed":357,"user":{"displayName":"Ethan C Campbell","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GjCBYTiuomqOsCakND1k_5wj0kYvFY53Jt7kunt=s64","userId":"11255944928409084259"}},"outputId":"2dd7cdf7-58cf-4a1c-9e46-e454737be6e7"},"source":["# Slicing works similarly between .isel() (slice by index) and .sel() (slice by value):\n","data['U'].sel(time=datetime(2012,1,30,20,0,0),lat=-52.70605,lon=-13.0,depth=slice(2,147)) # slicing values don't have to be exact"],"execution_count":null,"outputs":[{"output_type":"execute_result","data":{"text/html":["
"],"text/plain":["\n","array([0.12589 , 0.050398, 0.057173, 0.061555, 0.057382], dtype=float32)\n","Coordinates:\n"," time datetime64[ns] 2012-01-30T20:00:00\n"," lat float32 -52.70605\n"," lon float32 -13.0\n"," * depth (depth) float32 2.1 26.25 65.0 105.0 146.5\n","Attributes:\n"," units: meters/second\n"," long_name: Zonal Component of Velocity (m/s)\n"," standard_name: UVEL\n"," mate: VVEL"]},"metadata":{"tags":[]},"execution_count":65}]},{"cell_type":"code","metadata":{"id":"uXM4BWzwY504","colab":{"base_uri":"https://localhost:8080/","height":306},"executionInfo":{"status":"ok","timestamp":1604345129628,"user_tz":480,"elapsed":324,"user":{"displayName":"Ethan C Campbell","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GjCBYTiuomqOsCakND1k_5wj0kYvFY53Jt7kunt=s64","userId":"11255944928409084259"}},"outputId":"701900d4-da49-4edf-d64c-7d4159730aed"},"source":["# Sometimes you don't know the exact coordinate values, so you can ask xarray to find the 'nearest' values:\n","data['U'].sel(time=datetime(2012,1,30),lat=-53,lon=-13,depth=2,method='nearest') # slicing values don't have to be exact"],"execution_count":null,"outputs":[{"output_type":"execute_result","data":{"text/html":["
"],"text/plain":["\n","array(0.128653, dtype=float32)\n","Coordinates:\n"," time datetime64[ns] 2012-01-30T20:00:00\n"," lat float32 -52.90755\n"," lon float32 -13.0\n"," depth float32 2.1\n","Attributes:\n"," units: meters/second\n"," long_name: Zonal Component of Velocity (m/s)\n"," standard_name: UVEL\n"," mate: VVEL"]},"metadata":{"tags":[]},"execution_count":67}]},{"cell_type":"code","metadata":{"id":"2wniUv3OaLez","colab":{"base_uri":"https://localhost:8080/","height":575},"executionInfo":{"status":"ok","timestamp":1604345992348,"user_tz":480,"elapsed":380,"user":{"displayName":"Ethan C Campbell","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GjCBYTiuomqOsCakND1k_5wj0kYvFY53Jt7kunt=s64","userId":"11255944928409084259"}},"outputId":"db26a95e-fd8f-4286-aba0-e0431605dcf6"},"source":["# Other examples of slicing to get a 2D NumPy array\n","\n","# Here, the remaining dimensions are latitude and longitude\n","# (because we've selected a single time and single depth)\n","display(data['U'].sel(time=datetime(2012,1,30,20),depth=2.1,\n"," lat=slice(-50,-40),lon=slice(0,120)))\n","\n","# Here, the remaining dimensions are depth and longitude\n","# (because we've selected a single time and single latitude)\n","display(data['U'].sel(time=datetime(2012,1,30,20),depth=slice(200,1000),\n"," lon=slice(-120,0)).sel(lat=-57,method='nearest'))"],"execution_count":null,"outputs":[{"output_type":"display_data","data":{"text/html":["
"],"text/plain":["\n","array([[0.140002, 0.129511, 0.119145, ..., 0.032177, 0.033488, 0.035995],\n"," [0.134399, 0.124342, 0.114391, ..., 0.031455, 0.032763, 0.035228],\n"," [0.123725, 0.114466, 0.105262, ..., 0.029983, 0.031231, 0.033597],\n"," [0.106912, 0.098912, 0.090874, ..., 0.027764, 0.028964, 0.031245]],\n"," dtype=float32)\n","Coordinates:\n"," time datetime64[ns] 2012-01-30T20:00:00\n"," lat float32 -56.926678\n"," * lon (lon) float32 -120.0 -119.66667 -119.33333 ... -0.3333435 0.0\n"," * depth (depth) float32 220.0 301.0 450.0 700.0\n","Attributes:\n"," units: meters/second\n"," long_name: Zonal Component of Velocity (m/s)\n"," standard_name: UVEL\n"," mate: VVEL"]},"metadata":{"tags":[]}}]},{"cell_type":"code","metadata":{"id":"dGDa7r38d1Fc","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1604346606097,"user_tz":480,"elapsed":316,"user":{"displayName":"Ethan C Campbell","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GjCBYTiuomqOsCakND1k_5wj0kYvFY53Jt7kunt=s64","userId":"11255944928409084259"}},"outputId":"b8efd785-f8e6-4008-b3bc-26ec23b65fc1"},"source":["# You can reduce data from an xarray DataFrame by applying a NumPy function:\n","\n","# .mean() calculates the average over both of the remaining axes (depth and latitude)\n","print(data['U'].sel(time=datetime(2012,1,30,20),depth=2.1,\n"," lat=slice(-50,-40),lon=slice(0,120)).mean().item())"],"execution_count":null,"outputs":[{"output_type":"stream","text":["0.16497819125652313\n"],"name":"stdout"}]},{"cell_type":"code","metadata":{"id":"Q9ZT45eDgOdr","colab":{"base_uri":"https://localhost:8080/","height":216},"executionInfo":{"status":"ok","timestamp":1604346750003,"user_tz":480,"elapsed":287,"user":{"displayName":"Ethan C Campbell","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GjCBYTiuomqOsCakND1k_5wj0kYvFY53Jt7kunt=s64","userId":"11255944928409084259"}},"outputId":"98bad938-731e-4697-e66f-3991536c3765"},"source":["# .mean(dim='lon') calculates the average across the longitude dimension,\n","# leaving only latitude as the remaining dimension\n","display(data['U'].sel(time=datetime(2012,1,30,20),depth=2.1,\n"," lat=slice(-50,-40),lon=slice(0,120)).mean(dim='lon'))"],"execution_count":null,"outputs":[{"output_type":"display_data","data":{"text/html":["
"],"text/plain":["\n","array([0.19636832, 0.19726074, 0.19570175, 0.19753072, 0.1995998 ,\n"," 0.20088746, 0.20197098, 0.20239758, 0.20189096, 0.20043223,\n"," 0.19856165, 0.19670185, 0.19461559, 0.19198534, 0.18877912,\n"," 0.18521579, 0.18209256, 0.18030445, 0.1799029 , 0.18019168,\n"," 0.17991017, 0.17799716, 0.17403169, 0.1685389 , 0.16236207,\n"," 0.15637264, 0.15085906, 0.14584213, 0.14138193, 0.13736448,\n"," 0.13341603, 0.12943429, 0.12593448, 0.12360686, 0.12302325,\n"," 0.12359596, 0.12365858, 0.1221991 , 0.11970461, 0.11638598,\n"," 0.11225116, 0.10882197], dtype=float32)\n","Coordinates:\n"," time datetime64[ns] 2012-01-30T20:00:00\n"," * lat (lat) float32 -49.78614 -49.570454 ... -40.405617 -40.151318\n"," depth float32 2.1"]},"metadata":{"tags":[]}}]},{"cell_type":"code","metadata":{"id":"Z57CSoKfibWn","colab":{"base_uri":"https://localhost:8080/","height":300},"executionInfo":{"status":"ok","timestamp":1604347759903,"user_tz":480,"elapsed":427,"user":{"displayName":"Ethan C Campbell","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GjCBYTiuomqOsCakND1k_5wj0kYvFY53Jt7kunt=s64","userId":"11255944928409084259"}},"outputId":"f5ef3c7d-7f98-4867-e9a1-d92ec42b48f2"},"source":["# Save the result (keeping it in xarray format, not NumPy, to keep the latitude coordinate)\n","lat_velocities = data['U'].sel(time=datetime(2012,1,30,20),depth=2.1,\n"," lat=slice(-50,-40),lon=slice(0,120)).mean(dim='lon')\n","\n","# So this gave the eastward velocity averaged over all longitudes in the swath,\n","# so it's a 1-D array (a line) over latitude\n","plt.figure(figsize=(4,4))\n","plt.plot(lat_velocities['lat'],lat_velocities.values,c='k')\n","plt.xlabel('Latitude (°N)')\n","plt.ylabel('Eastward velocity (m/s)')\n","plt.grid()"],"execution_count":null,"outputs":[{"output_type":"display_data","data":{"image/png":"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\n","text/plain":["