diff --git a/lectures/pandas.md b/lectures/pandas.md new file mode 100644 index 0000000..70e7b5d --- /dev/null +++ b/lectures/pandas.md @@ -0,0 +1,814 @@ +--- +jupytext: + text_representation: + extension: .md + format_name: myst + format_version: 0.13 + jupytext_version: 1.16.7 +kernelspec: + display_name: Python 3 (ipykernel) + language: python + name: python3 +translation: + title: Pandas + headings: + Overview: Overview + Series: Series + DataFrames: DataFrames + DataFrames::Select Data by Position: Select Data by Position + DataFrames::Select Data by Conditions: Select Data by Conditions + DataFrames::Apply Method: Apply Method + DataFrames::Make Changes in DataFrames: Make Changes in DataFrames + DataFrames::Standardization and Visualization: Standardization and Visualization + On-Line Data Sources: On-Line Data Sources + On-Line Data Sources::Accessing Data with requests: Accessing Data with requests + On-Line Data Sources::Using wbgapi and yfinance to Access Data: Using wbgapi and yfinance to Access Data + Exercises: Exercises +--- + +(pd)= +```{raw} jupyter +
+ + QuantEcon + +
+``` + +# {index}`Pandas ` + +```{index} single: Python; Pandas +``` + +Anaconda-യിൽ ഉള്ളതിന് പുറമെ, ഈ lecture-ന് താഴെപ്പറയുന്ന libraries ആവശ്യമാണ്: + +```{code-cell} ipython3 +:tags: [hide-output] + +!pip install --upgrade wbgapi +!pip install --upgrade yfinance +``` + +## Overview + +[Pandas](https://pandas.pydata.org/) എന്നത് Python-നുള്ള വേഗതയേറിയതും കാര്യക്ഷമവുമായ data analysis tools-ന്റെ ഒരു package ആണ്. + +data science, machine learning തുടങ്ങിയ മേഖലകളുടെ വളർച്ചയ്‌ക്കൊപ്പം ഇതിന്റെ popularity കഴിഞ്ഞ വർഷങ്ങളിൽ കുതിച്ചുയർന്നിട്ടുണ്ട്. + +Stack Overflow Trends-ന്റെ സഹായത്തോടെ Matlab, STATA എന്നിവയുമായി താരതമ്യപ്പെടുത്തി കാലക്രമേണ ഉള്ള ഒരു popularity comparison ഇതാ + +```{figure} /_static/lecture_specific/pandas/pandas_vs_rest.png +:scale: 100 +``` + +[NumPy](https://numpy.org/) അടിസ്ഥാന array data type-ഉം core array operations-ഉം നൽകുന്നത് പോലെ, pandas + +1. data-യുമായി പ്രവർത്തിക്കാൻ ആവശ്യമായ fundamental structures define ചെയ്യുന്നു, ഒപ്പം +1. താഴെപ്പറയുന്നത് പോലുള്ള operations എളുപ്പമാക്കുന്ന methods അവയ്ക്ക് നൽകുന്നു + * data reading ചെയ്യുക + * indices adjust ചെയ്യുക + * dates, time series എന്നിവയുമായി പ്രവർത്തിക്കുക + * sorting, grouping, re-ordering, general data munging [^mung] + * missing values കൈകാര്യം ചെയ്യുക, തുടങ്ങിയവ + +കൂടുതൽ sophisticated ആയ statistical functionality [statsmodels](https://www.statsmodels.org/), [scikit-learn](https://scikit-learn.org/) പോലുള്ള pandas-ന്റെ മുകളിൽ built ചെയ്ത മറ്റ് packages-നായി വിട്ടിരിക്കുന്നു. + +ഈ lecture pandas-നെ കുറിച്ചുള്ള ഒരു basic introduction നൽകും. + +ലക്ചർ മുഴുവൻ, താഴെപ്പറയുന്ന imports നടന്നിട്ടുണ്ട് എന്ന് നമ്മൾ assume ചെയ്യും + +```{code-cell} ipython3 +import pandas as pd +import numpy as np +import matplotlib.pyplot as plt +import requests +``` + +pandas define ചെയ്യുന്ന രണ്ട് പ്രധാന data types `Series`-ഉം `DataFrame`-ഉം ആണ്. + +`Series`-നെ data-യുടെ ഒരു "column" ആയി ചിന്തിക്കാം, ഒരു single variable-ന്റെ observations-ന്റെ ഒരു collection പോലെ. + +related columns of data സൂക്ഷിക്കാനുള്ള ഒരു two-dimensional object ആണ് `DataFrame`. + +## Series + +```{index} single: Pandas; Series +``` + +നമുക്ക് Series-ൽ നിന്ന് തുടങ്ങാം. + +നാല് random observations-ന്റെ ഒരു series create ചെയ്തുകൊണ്ട് നമ്മൾ ആരംഭിക്കുന്നു + +```{code-cell} ipython3 +s = pd.Series(np.random.randn(4), name='daily returns') +s +``` + +ഇവിടെ `0, 1, 2, 3` എന്ന indices നാല് listed companies-നെ index ചെയ്യുന്നതായും, values അവയുടെ shares-ന്റെ daily returns ആയും നിങ്ങൾക്ക് സങ്കൽപ്പിക്കാം. + +Pandas `Series` NumPy arrays-ന്റെ മുകളിൽ built ചെയ്തതാണ്, അതിനാൽ സമാനമായ പല operations-ഉം support ചെയ്യുന്നു + +```{code-cell} ipython3 +s * 100 +``` + +```{code-cell} ipython3 +np.abs(s) +``` + +എന്നാൽ `Series` NumPy arrays-നേക്കാൾ കൂടുതൽ നൽകുന്നു. + +അധിക (statistically oriented) methods ഉള്ളതിന് പുറമെ + +```{code-cell} ipython3 +s.describe() +``` + +അവയുടെ indices കൂടുതൽ flexible ആണ് + +```{code-cell} ipython3 +s.index = ['AMZN', 'AAPL', 'MSFT', 'GOOG'] +s +``` + +ഈ രീതിയിൽ കാണുമ്പോൾ, `Series` വേഗതയേറിയതും കാര്യക്ഷമവുമായ Python dictionaries-നെ പോലെയാണ് (dictionary-യിലെ items എല്ലാം ഒരേ type-ന്റെ ആയിരിക്കണം എന്ന restriction ഉണ്ട്---ഈ case-ൽ, floats). + +വാസ്തവത്തിൽ, Python dictionaries-ൽ ഉപയോഗിക്കുന്ന syntax തന്നെ നിങ്ങൾക്ക് ഉപയോഗിക്കാം + +```{code-cell} ipython3 +s['AMZN'] +``` + +```{code-cell} ipython3 +s['AMZN'] = 0 +s +``` + +```{code-cell} ipython3 +'AAPL' in s +``` + +## DataFrames + +```{index} single: Pandas; DataFrames +``` + +`Series` data-യുടെ ഒറ്റ column ആണെങ്കിൽ, `DataFrame` ഓരോ variable-നും ഒരു column വീതം ഉള്ള പല columns ആണ്. + +അടിസ്ഥാനപരമായി, pandas-ലെ `DataFrame` ഒരു (highly optimized) Excel spreadsheet-ന് സമാനമാണ്. + +അതിനാൽ, rows-ഉം columns-ഉം ആയി സ്വാഭാവികമായി organize ചെയ്യപ്പെട്ട data represent ചെയ്യാനും analyze ചെയ്യാനും ഉള്ള ശക്തമായ ഒരു tool ആണിത്, individual rows-നും individual columns-നും വേണ്ടി descriptive indexes ഉള്ളതോടെ. + +[Penn World Tables](https://www.rug.nl/ggdc/productivity/pwt/pwt-releases/pwt-7.0)-ൽ നിന്ന് എടുത്ത `pandas/data/test_pwt.csv` എന്ന CSV file-ൽ നിന്ന് data read ചെയ്യുന്ന ഒരു example നോക്കാം. + +Dataset-ൽ താഴെപ്പറയുന്ന indicators അടങ്ങിയിരിക്കുന്നു + +| Variable Name | Description | +| :-: | :-: | +| POP | Population (in thousands) | +| XRAT | Exchange Rate to US Dollar | +| tcgdp | Total PPP Converted GDP (in million international dollar) | +| cc | Consumption Share of PPP Converted GDP Per Capita (%) | +| cg | Government Consumption Share of PPP Converted GDP Per Capita (%) | + + +`pandas` function ആയ `read_csv` ഉപയോഗിച്ച് നമ്മൾ ഇത് ഒരു URL-ൽ നിന്ന് read ചെയ്യും. + +```{code-cell} ipython3 +df = pd.read_csv('https://raw.githubusercontent.com/QuantEcon/lecture-python-programming/main/lectures/_static/lecture_specific/pandas/data/test_pwt.csv') +type(df) +``` + +`test_pwt.csv`-ന്റെ content ഇതാ + +```{code-cell} ipython3 +df +``` + +### Select Data by Position + +Practice-ൽ, നമ്മൾ എപ്പോഴും ചെയ്യുന്ന ഒരു കാര്യം നമ്മുടെ interest ഉള്ള data-യുടെ ഒരു subset find ചെയ്യുകയും select ചെയ്യുകയും അതുമായി പ്രവർത്തിക്കുകയും ചെയ്യുക എന്നതാണ്. + +standard Python array slicing notation ഉപയോഗിച്ച് നമുക്ക് particular rows select ചെയ്യാം + +```{code-cell} ipython3 +df[2:5] +``` + +Columns select ചെയ്യാൻ, ആവശ്യമുള്ള columns-ന്റെ names strings ആയി represent ചെയ്യുന്ന ഒരു list നമുക്ക് pass ചെയ്യാം + +```{code-cell} ipython3 +df[['country', 'tcgdp']] +``` + +integers ഉപയോഗിച്ച് rows-ഉം columns-ഉം select ചെയ്യാൻ, `.iloc[rows, columns]` എന്ന format-ൽ `iloc` attribute ഉപയോഗിക്കണം. + +```{code-cell} ipython3 +df.iloc[2:5, 0:4] +``` + +integers-ഉം labels-ഉം കൂടിക്കലർത്തി rows-ഉം columns-ഉം select ചെയ്യാൻ, `loc` attribute സമാനമായ രീതിയിൽ ഉപയോഗിക്കാം + +```{code-cell} ipython3 +df.loc[df.index[2:5], ['country', 'tcgdp']] +``` + +### Select Data by Conditions + +integers-ഉം names-ഉം ഉപയോഗിച്ച് rows-ഉം columns-ഉം index ചെയ്യുന്നതിന് പകരം, ചില (potentially complicated) conditions satisfy ചെയ്യുന്ന നമ്മുടെ interest ഉള്ള ഒരു sub-dataframe-ഉം നമുക്ക് ലഭിക്കും. + +ഇത് ചെയ്യാനുള്ള വിവിധ വഴികൾ ഈ section demonstrate ചെയ്യുന്നു. + +ഏറ്റവും straightforward ആയ വഴി `[]` operator ഉപയോഗിച്ചാണ്. + +```{code-cell} ipython3 +df[df.POP >= 20000] +``` + +ഇവിടെ എന്താണ് സംഭവിക്കുന്നത് എന്ന് മനസ്സിലാക്കാൻ, `df.POP >= 20000` boolean values-ന്റെ ഒരു series return ചെയ്യുന്നു എന്ന് ശ്രദ്ധിക്കുക. + +```{code-cell} ipython3 +df.POP >= 20000 +``` + +ഈ case-ൽ, `df[___]` boolean values-ന്റെ ഒരു series എടുത്ത് `True` values ഉള്ള rows മാത്രം return ചെയ്യുന്നു. + +ഒരു ഉദാഹരണം കൂടി എടുക്കാം, + +```{code-cell} ipython3 +df[(df.country.isin(['Argentina', 'India', 'South Africa'])) & (df.POP > 40000)] +``` + +എന്നിരുന്നാലും, ഇതേ കാര്യം ചെയ്യാൻ മറ്റൊരു വഴിയുണ്ട്, അത് വലിയ dataframes-ന് കുറച്ചുകൂടി വേഗതയേറിയതും, കൂടുതൽ natural ആയ syntax-ഉള്ളതും ആണ്. + +```{code-cell} ipython3 +# the above is equivalent to +df.query("POP >= 20000") +``` + +```{code-cell} ipython3 +df.query("country in ['Argentina', 'India', 'South Africa'] and POP > 40000") +``` + +വ്യത്യസ്ത columns-ന് ഇടയിൽ arithmetic operations-ഉം നമുക്ക് allow ചെയ്യാം. + +```{code-cell} ipython3 +df[(df.cc + df.cg >= 80) & (df.POP <= 20000)] +``` + +```{code-cell} ipython3 +# the above is equivalent to +df.query("cc + cg >= 80 & POP <= 20000") +``` + +ഉദാഹരണത്തിന്, ഏറ്റവും വലിയ household consumption - gdp share `cc` ഉള്ള country select ചെയ്യാൻ conditioning ഉപയോഗിക്കാം. + +```{code-cell} ipython3 +df.loc[df.cc == max(df.cc)] +``` + +selected sub-dataframe-ന്റെ ചില columns മാത്രം നമുക്ക് നോക്കണമെങ്കിൽ, മുകളിലുള്ള conditions `.loc[__ , __]` command-ഉമായി ഉപയോഗിക്കാം. + +ആദ്യത്തെ argument condition എടുക്കുന്നു, രണ്ടാമത്തെ argument നമുക്ക് return വേണ്ട columns-ന്റെ ഒരു list എടുക്കുന്നു. + +```{code-cell} ipython3 +df.loc[(df.cc + df.cg >= 80) & (df.POP <= 20000), ['country', 'year', 'POP']] +``` + +**Application: Subsetting Dataframe** + +Real-world datasets [enormous](https://developers.google.com/machine-learning/crash-course/overfitting) ആയിരിക്കാം. + +computational efficiency വർദ്ധിപ്പിക്കാനും redundancy കുറയ്ക്കാനും data-യുടെ ഒരു subset ഉപയോഗിച്ച് പ്രവർത്തിക്കുന്നത് ചിലപ്പോൾ desirable ആണ്. + +Population (`POP`)-ഉം total GDP (`tcgdp`)-ഉം മാത്രമേ നമുക്ക് interest ഉള്ളൂ എന്ന് സങ്കൽപ്പിക്കാം. + +`df` എന്ന data frame ഈ variables മാത്രം ആയി strip ചെയ്യാനുള്ള ഒരു വഴി, മുകളിൽ വിവരിച്ച selection method ഉപയോഗിച്ച് dataframe overwrite ചെയ്യുക എന്നതാണ് + +```{code-cell} ipython3 +df_subset = df[['country', 'POP', 'tcgdp']] +df_subset +``` + +തുടർന്ന്, further analysis-ന് വേണ്ടി ഈ ചെറിയ dataset നമുക്ക് save ചെയ്യാം. + +```{code-block} python3 +:class: no-execute + +df_subset.to_csv('pwt_subset.csv', index=False) +``` + +### Apply Method + +വ്യാപകമായി ഉപയോഗിക്കുന്ന മറ്റൊരു Pandas method ആണ് `df.apply()`. + +ഇത് ഓരോ row/column-നും ഒരു function apply ചെയ്യുകയും ഒരു series return ചെയ്യുകയും ചെയ്യുന്നു. + +ഈ function `max` function പോലുള്ള ചില built-in functions, ഒരു `lambda` function, അല്ലെങ്കിൽ ഒരു user-defined function ആകാം. + +`max` function ഉപയോഗിച്ചുള്ള ഒരു ഉദാഹരണം ഇതാ + +```{code-cell} ipython3 +df[['year', 'POP', 'XRAT', 'tcgdp', 'cc', 'cg']].apply(max) +``` + +ഈ code-ന്റെ line എല്ലാ selected columns-ലും `max` function apply ചെയ്യുന്നു. + +`df.apply()` method-ഉമായി `lambda` function പലപ്പോഴും ഉപയോഗിക്കാറുണ്ട് + +dataframe-ലെ ഓരോ row-ക്കും തന്നെ return ചെയ്യുക എന്നത് ഒരു trivial ഉദാഹരണമാണ് + +```{code-cell} ipython3 +df.apply(lambda row: row, axis=1) +``` + +```{note} +`.apply()` method-ന് +- axis = 0 -- ഓരോ column-നും (variables) function apply ചെയ്യുന്നു +- axis = 1 -- ഓരോ row-ക്കും (observations) function apply ചെയ്യുന്നു +- axis = 0 ആണ് default parameter +``` + +കൂടുതൽ advanced ആയ selection ചെയ്യാൻ `.loc[]`-ഉമായി ചേർത്ത് നമുക്ക് ഇത് ഉപയോഗിക്കാം. + +```{code-cell} ipython3 +complexCondition = df.apply( + lambda row: row.POP > 40000 if row.country in ['Argentina', 'India', 'South Africa'] else row.POP < 20000, + axis=1), ['country', 'year', 'POP', 'XRAT', 'tcgdp'] +``` + +if-else statement-ൽ specify ചെയ്ത condition satisfy ചെയ്യുന്ന rows-ന്റെ boolean values-ന്റെ ഒരു series ഇവിടെ `df.apply()` return ചെയ്യുന്നു. + +കൂടാതെ, interest ഉള്ള variables-ന്റെ ഒരു subset-ഉം ഇത് define ചെയ്യുന്നു. + +```{code-cell} ipython3 +complexCondition +``` + +ഈ condition dataframe-ൽ apply ചെയ്യുമ്പോൾ, result ഇതായിരിക്കും + +```{code-cell} ipython3 +df.loc[complexCondition] +``` + +### Make Changes in DataFrames + +future analysis-ന് വേണ്ടി ഒരു clean dataset generate ചെയ്യാൻ dataframes-ൽ changes ഉണ്ടാക്കാനുള്ള ability പ്രധാനമാണ്. + + +**1.** നമ്മൾ select ചെയ്ത rows "keep" ചെയ്യാനും ബാക്കിയുള്ള rows `NaN` ആയി replace ചെയ്യാനും `df.where()` സൗകര്യപ്രദമായി ഉപയോഗിക്കാം + +```{code-cell} ipython3 +df.where(df.POP >= 20000) +``` + +**2.** modify ചെയ്യേണ്ട column specify ചെയ്യാൻ `.loc[]` ലളിതമായി ഉപയോഗിച്ച് values assign ചെയ്യാം + +```{code-cell} ipython3 +df.loc[df.cg == max(df.cg), 'cg'] = np.nan +df +``` + +**3.** *rows/columns as a whole* modify ചെയ്യാൻ `.apply()` method ഉപയോഗിക്കാം + +```{code-cell} ipython3 +def update_row(row): + # modify POP + row.POP = np.nan if row.POP<= 10000 else row.POP + + # modify XRAT + row.XRAT = row.XRAT / 10 + return row + +df.apply(update_row, axis=1) +``` + +**4.** dataframe-ലെ എല്ലാ *individual entries*-ഉം ഒരുമിച്ച് modify ചെയ്യാൻ `.map()` method ഉപയോഗിക്കാം. + +```{code-cell} ipython3 +# Round all decimal numbers to 2 decimal places +df.map(lambda x : round(x,2) if type(x)!=str else x) +``` + +**Application: Missing Value Imputation** + +Missing values replace ചെയ്യുന്നത് data munging-ലെ ഒരു പ്രധാന step ആണ്. + +നമുക്ക് randomly ചില NaN values insert ചെയ്യാം + +```{code-cell} ipython3 +for idx in list(zip([0, 3, 5, 6], [3, 4, 6, 2])): + df.iloc[idx] = np.nan + +df +``` + +ഇവിടെ `zip()` function രണ്ട് lists-ൽ നിന്ന് values-ന്റെ pairs create ചെയ്യുന്നു (അതായത് [0,3], [3,4] ...) + +എല്ലാ missing values-ഉം 0 ആയി replace ചെയ്യാൻ വീണ്ടും `.map()` method നമുക്ക് ഉപയോഗിക്കാം + +```{code-cell} ipython3 +# replace all NaN values by 0 +def replace_nan(x): + if type(x)!=str: + return 0 if np.isnan(x) else x + else: + return x + +df.map(replace_nan) +``` + +Missing values replace ചെയ്യാൻ Pandas നമുക്ക് സൗകര്യപ്രദമായ methods-ഉം നൽകുന്നു. + +ഉദാഹരണത്തിന്, variable means ഉപയോഗിച്ചുള്ള single imputation pandas-ൽ എളുപ്പത്തിൽ ചെയ്യാം + +```{code-cell} ipython3 +df = df.fillna(df.iloc[:,2:8].mean()) +df +``` + +Missing value imputation എന്നത് വിവിധ machine learning techniques ഉൾപ്പെടുന്ന data science-ലെ ഒരു വലിയ area ആണ്. + +missing values impute ചെയ്യാൻ python-ൽ കൂടുതൽ [advanced tools](https://scikit-learn.org/stable/modules/impute.html)-ഉം ഉണ്ട്. + +### Standardization and Visualization + +Population (`POP`)-ഉം total GDP (`tcgdp`)-ഉം മാത്രമേ നമുക്ക് interest ഉള്ളൂ എന്ന് സങ്കൽപ്പിക്കാം. + +`df` എന്ന data frame ഈ variables മാത്രം ആയി strip ചെയ്യാനുള്ള ഒരു വഴി, മുകളിൽ വിവരിച്ച selection method ഉപയോഗിച്ച് dataframe overwrite ചെയ്യുക എന്നതാണ് + +```{code-cell} ipython3 +df = df[['country', 'POP', 'tcgdp']] +df +``` + +ഇവിടെ `0, 1,..., 7` എന്ന index redundant ആണ്, കാരണം country names-നെ ഒരു index ആയി നമുക്ക് ഉപയോഗിക്കാം. + +ഇത് ചെയ്യാൻ, dataframe-ലെ `country` variable-നെ index ആയി നമ്മൾ set ചെയ്യുന്നു + +```{code-cell} ipython3 +df = df.set_index('country') +df +``` + +Columns-ന് അൽപ്പം മെച്ചപ്പെട്ട names നൽകാം + +```{code-cell} ipython3 +df.columns = 'population', 'total GDP' +df +``` + +`population` variable thousands-ൽ ആണ്, single units-ലേക്ക് നമുക്ക് മാറ്റാം + +```{code-cell} ipython3 +df['population'] = df['population'] * 1e3 +df +``` + +അടുത്തതായി, real GDP per capita കാണിക്കുന്ന ഒരു column നമ്മൾ ചേർക്കാൻ പോകുന്നു, total GDP millions-ൽ ആയതിനാൽ 1,000,000 കൊണ്ട് multiply ചെയ്യുന്നു + +```{code-cell} ipython3 +df['GDP percap'] = df['total GDP'] * 1e6 / df['population'] +df +``` + +pandas `DataFrame`-ഉം `Series` objects-ഉം സംബന്ധിച്ച നല്ല ഒരു കാര്യം, Matplotlib വഴി പ്രവർത്തിക്കുന്ന plotting-നും visualization-നും വേണ്ടിയുള്ള methods അവയ്ക്ക് ഉണ്ട് എന്നതാണ്. + +ഉദാഹരണത്തിന്, GDP per capita-യുടെ ഒരു bar plot നമുക്ക് എളുപ്പത്തിൽ generate ചെയ്യാം + +```{code-cell} ipython3 +ax = df['GDP percap'].plot(kind='bar') +ax.set_xlabel('country', fontsize=12) +ax.set_ylabel('GDP per capita', fontsize=12) +plt.show() +``` + +ഇപ്പോൾ data frame countries-ന്റെ alphabetical order-ൽ ആണ്---GDP per capita-ന്റെ order-ലേക്ക് നമുക്ക് അത് മാറ്റാം + +```{code-cell} ipython3 +df = df.sort_values(by='GDP percap', ascending=False) +df +``` + +മുൻപത്തെപ്പോലെ plot ചെയ്യുമ്പോൾ ഇപ്പോൾ ഇത് ലഭിക്കുന്നു + +```{code-cell} ipython3 +ax = df['GDP percap'].plot(kind='bar') +ax.set_xlabel('country', fontsize=12) +ax.set_ylabel('GDP per capita', fontsize=12) +plt.show() +``` + +## On-Line Data Sources + +```{index} single: Data Sources +``` + +online databases-നെ programmatically query ചെയ്യുന്നത് Python straightforward ആക്കുന്നു. + +economists-ന് ഒരു പ്രധാന database ആണ് [FRED](https://fred.stlouisfed.org/) --- St. Louis Fed maintain ചെയ്യുന്ന time series data-യുടെ ഒരു വലിയ collection. + +ഉദാഹരണത്തിന്, [unemployment rate](https://fred.stlouisfed.org/series/UNRATE)-ൽ നമുക്ക് interest ഉണ്ട് എന്ന് കരുതുക. + +(data csv ആയി download ചെയ്യാൻ, top right-ലെ `Download` click ചെയ്ത് `CSV (data)` option select ചെയ്യുക). + +പകരമായി, ഒരു Python program-ൽ നിന്ന് നമുക്ക് CSV file access ചെയ്യാം. + +ഇത് പല രീതികളിലും ചെയ്യാം. + +താരതമ്യേന low-level ആയ ഒരു method-ൽ നമ്മൾ ആരംഭിച്ച് പിന്നീട് pandas-ലേക്ക് തിരിച്ചുവരും. + +### Accessing Data with {index}`requests ` + +```{index} single: Python; requests +``` + +Internet-ൽ നിന്ന് data request ചെയ്യാനുള്ള standard Python library ആയ [requests](https://requests.readthedocs.io/en/latest/) ഉപയോഗിക്കുന്നതാണ് ഒരു option. + +തുടങ്ങാൻ, നിങ്ങളുടെ computer-ൽ താഴെപ്പറയുന്ന code try ചെയ്യുക + +```{code-cell} ipython3 +r = requests.get('https://fred.stlouisfed.org/graph/fredgraph.csv?bgcolor=%23e1e9f0&chart_type=line&drp=0&fo=open%20sans&graph_bgcolor=%23ffffff&height=450&mode=fred&recession_bars=on&txtcolor=%23444444&ts=12&tts=12&width=1318&nt=0&thu=0&trc=0&show_legend=yes&show_axis_titles=yes&show_tooltip=yes&id=UNRATE&scale=left&cosd=1948-01-01&coed=2024-06-01&line_color=%234572a7&link_values=false&line_style=solid&mark_type=none&mw=3&lw=2&ost=-99999&oet=99999&mma=0&fml=a&fq=Monthly&fam=avg&fgst=lin&fgsnd=2020-02-01&line_index=1&transformation=lin&vintage_date=2024-07-29&revision_date=2024-07-29&nd=1948-01-01') +``` + +Error message ഒന്നും ഇല്ലെങ്കിൽ, call succeed ആയി എന്നാണ് അർത്ഥം. + +Error ലഭിച്ചാൽ, സാധ്യതയുള്ള രണ്ട് കാരണങ്ങൾ ഉണ്ട് + +1. നിങ്ങൾ Internet-ലേക്ക് connect ആയിട്ടില്ല --- ഇത് സംഭവിക്കില്ല എന്ന് പ്രതീക്ഷിക്കുന്നു. +1. നിങ്ങളുടെ machine ഒരു proxy server വഴിയാണ് Internet access ചെയ്യുന്നത്, Python-ന് ഇത് അറിയില്ല. + +രണ്ടാമത്തെ case-ൽ, നിങ്ങൾക്ക് ഒന്നുകിൽ + +* മറ്റൊരു machine-ലേക്ക് switch ചെയ്യാം +* [the documentation](https://requests.readthedocs.io/en/latest/) വായിച്ച് നിങ്ങളുടെ proxy problem പരിഹരിക്കാം + +എല്ലാം work ചെയ്യുന്നു എന്ന് assume ചെയ്താൽ, `requests.get('https://research.stlouisfed.org/fred2/series/UNRATE/downloaddata/UNRATE.csv')` എന്ന call return ചെയ്ത `source` object നിങ്ങൾക്ക് ഇപ്പോൾ ഉപയോഗിക്കാം + +```{code-cell} ipython3 +url = 'https://fred.stlouisfed.org/graph/fredgraph.csv?bgcolor=%23e1e9f0&chart_type=line&drp=0&fo=open%20sans&graph_bgcolor=%23ffffff&height=450&mode=fred&recession_bars=on&txtcolor=%23444444&ts=12&tts=12&width=1318&nt=0&thu=0&trc=0&show_legend=yes&show_axis_titles=yes&show_tooltip=yes&id=UNRATE&scale=left&cosd=1948-01-01&coed=2024-06-01&line_color=%234572a7&link_values=false&line_style=solid&mark_type=none&mw=3&lw=2&ost=-99999&oet=99999&mma=0&fml=a&fq=Monthly&fam=avg&fgst=lin&fgsnd=2020-02-01&line_index=1&transformation=lin&vintage_date=2024-07-29&revision_date=2024-07-29&nd=1948-01-01' +source = requests.get(url).content.decode().split("\n") +source[0] +``` + +```{code-cell} ipython3 +source[1] +``` + +```{code-cell} ipython3 +source[2] +``` + +ഈ text parse ചെയ്ത് ഒരു array ആയി store ചെയ്യാൻ നമുക്ക് ഇപ്പോൾ കുറച്ച് additional code എഴുതാം. + +എന്നാൽ ഇത് unnecessary ആണ് --- pandas-ന്റെ `read_csv` function ഈ task നമുക്കായി handle ചെയ്യും. + +pandas നമ്മുടെ dates column recognize ചെയ്യാൻ `parse_dates=True` നമ്മൾ ഉപയോഗിക്കുന്നു, ഇത് simple date filtering-ന് അനുവദിക്കുന്നു + +```{code-cell} ipython3 +data = pd.read_csv(url, index_col=0, parse_dates=True) +``` + +`data` എന്ന ഒരു pandas DataFrame-ലേക്ക് data read ചെയ്തിരിക്കുന്നു, ഇത് ഇപ്പോൾ പതിവ് രീതിയിൽ നമുക്ക് manipulate ചെയ്യാം + +```{code-cell} ipython3 +type(data) +``` + +```{code-cell} ipython3 +data.head() # A useful method to get a quick look at a data frame +``` + +```{code-cell} ipython3 +pd.set_option('display.precision', 1) +data.describe() # Your output might differ slightly +``` + +2006 മുതൽ 2012 വരെയുള്ള unemployment rate ഇങ്ങനെയും നമുക്ക് plot ചെയ്യാം + +```{code-cell} ipython3 +ax = data['2006':'2012'].plot(title='US Unemployment Rate', legend=False) +ax.set_xlabel('year', fontsize=12) +ax.set_ylabel('%', fontsize=12) +plt.show() +``` + +pandas മറ്റ് പല file type alternatives-ഉം offer ചെയ്യുന്നു എന്നത് ശ്രദ്ധിക്കുക. + +Read, excel, json, parquet ചെയ്യാനോ ഒരു database server-ലേക്ക് നേരിട്ട് plug ചെയ്യാനോ നമുക്ക് ഉപയോഗിക്കാവുന്ന [a wide variety](https://pandas.pydata.org/pandas-docs/stable/user_guide/io.html) top-level methods Pandas-ന് ഉണ്ട്. + +### Using {index}`wbgapi ` and {index}`yfinance ` to Access Data + +World Bank publish ചെയ്യുന്ന പല databases-ൽ നിന്നും data fetch ചെയ്യാൻ [wbgapi](https://pypi.org/project/wbgapi/) python library ഉപയോഗിക്കാം. + +```{note} +[wbgapi](https://pypi.org/project/wbgapi/) package-നെ കുറിച്ചുള്ള useful ആയ ചില information ഈ [world bank blog post](https://blogs.worldbank.org/en/opendata/introducing-wbgapi-new-python-package-accessing-world-bank-data)-ൽ, കൂടാതെ ഈ [tutorial](https://github.com/tgherzog/wbgapi/blob/master/examples/wbgapi-quickstart.ipynb)-ലും നിങ്ങൾക്ക് കണ്ടെത്താം +``` + +Exercises-ൽ Yahoo finance-ൽ നിന്ന് data fetch ചെയ്യാൻ [yfinance](https://pypi.org/project/yfinance/)-ഉം നമ്മൾ ഉപയോഗിക്കും. + +ഇപ്പോൾ data download ചെയ്ത് plot ചെയ്യുന്നതിന്റെ ഒരു example നമുക്ക് നോക്കാം --- ഇത്തവണ World Bank-ൽ നിന്ന്. + +World Bank ഒരു വലിയ range indicators-ൽ data [collect ചെയ്ത് organize ചെയ്യുന്നു](https://data.worldbank.org/indicator). + +ഉദാഹരണത്തിന്, GDP-യുടെ ratio ആയി government debt-നെക്കുറിച്ചുള്ള ചില data [ഇതാ](https://data.worldbank.org/indicator/GC.DOD.TOTL.GD.ZS). + +അടുത്ത code example നിങ്ങൾക്ക് വേണ്ടി data fetch ചെയ്ത് US-നും Australia-നും വേണ്ടിയുള്ള time series plot ചെയ്യുന്നു + +```{code-cell} ipython3 +import wbgapi as wb +wb.series.info('GC.DOD.TOTL.GD.ZS') +``` + +```{code-cell} ipython3 +govt_debt = wb.data.DataFrame('GC.DOD.TOTL.GD.ZS', economy=['USA','AUS'], time=range(2005,2016)) +govt_debt = govt_debt.T # move years from columns to rows for plotting +``` + +```{code-cell} ipython3 +govt_debt.plot(xlabel='year', ylabel='Government debt (% of GDP)'); +``` + +## Exercises + +```{exercise-start} +:label: pd_ex1 +``` + +ഈ imports ഉപയോഗിച്ച്: + +```{code-cell} ipython3 +import datetime as dt +import yfinance as yf +``` + +താഴെപ്പറയുന്ന shares-ന്റെ 2021-ലെ percentage price change calculate ചെയ്യാൻ ഒരു program എഴുതുക: + +```{code-cell} ipython3 +ticker_list = {'INTC': 'Intel', + 'MSFT': 'Microsoft', + 'IBM': 'IBM', + 'BHP': 'BHP', + 'TM': 'Toyota', + 'AAPL': 'Apple', + 'AMZN': 'Amazon', + 'C': 'Citigroup', + 'QCOM': 'Qualcomm', + 'KO': 'Coca-Cola', + 'GOOG': 'Google'} +``` + +program-ന്റെ ആദ്യ ഭാഗം ഇതാ + +```{code-cell} ipython3 +def read_data(ticker_list, + start=dt.datetime(2021, 1, 1), + end=dt.datetime(2021, 12, 31)): + """ + This function reads in closing price data from Yahoo + for each tick in the ticker_list. + """ + ticker = pd.DataFrame() + + for tick in ticker_list: + stock = yf.Ticker(tick) + prices = stock.history(start=start, end=end) + + # Change the index to date-only + prices.index = pd.to_datetime(prices.index.date) + + closing_prices = prices['Close'] + ticker[tick] = closing_prices + + return ticker + +ticker = read_data(ticker_list) +``` + +Result-നെ ഇതുപോലുള്ള ഒരു bar graph ആയി plot ചെയ്യാൻ program complete ചെയ്യുക: + +```{image} /_static/lecture_specific/pandas/pandas_share_prices.png +:scale: 80 +:align: center +``` + +```{exercise-end} +``` + +```{solution-start} pd_ex1 +:class: dropdown +``` + +percentage change calculate ചെയ്യാൻ Pandas ഉപയോഗിച്ച് ഈ problem approach ചെയ്യാൻ കുറച്ച് വഴികളുണ്ട്. + +ആദ്യമായി, നിങ്ങൾക്ക് data extract ചെയ്ത് ഇതുപോലെ calculation perform ചെയ്യാം: + +```{code-cell} ipython3 +p1 = ticker.iloc[0] #Get the first set of prices as a Series +p2 = ticker.iloc[-1] #Get the last set of prices as a Series +price_change = (p2 - p1) / p1 * 100 +price_change +``` + +പകരമായി `periods` argument ഉപയോഗിച്ച് ശരിയായ calculation perform ചെയ്യാൻ configure ചെയ്ത ഒരു inbuilt method `pct_change` നിങ്ങൾക്ക് ഉപയോഗിക്കാം. + +```{code-cell} ipython3 +change = ticker.pct_change(periods=len(ticker)-1, axis='rows')*100 +price_change = change.iloc[-1] +price_change +``` + +തുടർന്ന് chart plot ചെയ്യാൻ + +```{code-cell} ipython3 +price_change.sort_values(inplace=True) +price_change.rename(index=ticker_list, inplace=True) +``` + +```{code-cell} ipython3 +fig, ax = plt.subplots(figsize=(10,8)) +ax.set_xlabel('stock', fontsize=12) +ax.set_ylabel('percentage change in price', fontsize=12) +price_change.plot(kind='bar', ax=ax) +plt.show() +``` + +```{solution-end} +``` + + +```{exercise-start} +:label: pd_ex2 +``` + +{ref}`pd_ex1`-ൽ introduce ചെയ്ത `read_data` method ഉപയോഗിച്ച്, താഴെപ്പറയുന്ന indices-ന്റെ year-on-year percentage change obtain ചെയ്യാൻ ഒരു program എഴുതുക: + +```{code-cell} ipython3 +indices_list = {'^GSPC': 'S&P 500', + '^IXIC': 'NASDAQ', + '^DJI': 'Dow Jones', + '^N225': 'Nikkei'} +``` + +summary statistics കാണിക്കാനും result-നെ ഇതുപോലുള്ള ഒരു time series graph ആയി plot ചെയ്യാനും program complete ചെയ്യുക: + +```{image} /_static/lecture_specific/pandas/pandas_indices_pctchange.png +:scale: 80 +:align: center +``` + +```{exercise-end} +``` + +```{solution-start} pd_ex2 +:class: dropdown +``` + +{ref}`pd_ex1`-ൽ നിങ്ങൾ ചെയ്ത work പിന്തുടർന്ന്, start, end dates അതനുസരിച്ച് update ചെയ്ത് `read_data` ഉപയോഗിച്ച് data നിങ്ങൾക്ക് query ചെയ്യാം. + +```{code-cell} ipython3 +indices_data = read_data( + indices_list, + start=dt.datetime(1971, 1, 1), #Common Start Date + end=dt.datetime(2021, 12, 31) +) +``` + +തുടർന്ന്, ഓരോ വർഷത്തിലെയും prices-ന്റെ ആദ്യത്തെയും അവസാനത്തെയും set DataFrames ആയി extract ചെയ്ത്, ഇതുപോലെ yearly returns calculate ചെയ്യുക: + +```{code-cell} ipython3 +yearly_returns = pd.DataFrame() + +for index, name in indices_list.items(): + p1 = indices_data.groupby(indices_data.index.year)[index].first() # Get the first set of returns as a DataFrame + p2 = indices_data.groupby(indices_data.index.year)[index].last() # Get the last set of returns as a DataFrame + returns = (p2 - p1) / p1 + yearly_returns[name] = returns + +yearly_returns +``` + +അടുത്തതായി, `describe` method ഉപയോഗിച്ച് summary statistics നിങ്ങൾക്ക് obtain ചെയ്യാം. + +```{code-cell} ipython3 +yearly_returns.describe() +``` + +തുടർന്ന്, chart plot ചെയ്യാൻ + +```{code-cell} ipython3 +fig, axes = plt.subplots(2, 2, figsize=(10, 8)) + +for iter_, ax in enumerate(axes.flatten()): # Flatten 2-D array to 1-D array + index_name = yearly_returns.columns[iter_] # Get index name per iteration + ax.plot(yearly_returns[index_name]) # Plot pct change of yearly returns per index + ax.set_ylabel("percent change", fontsize = 12) + ax.set_title(index_name) + +plt.tight_layout() +``` + +```{solution-end} +``` + +[^mung]: raw data-യിൽ നിന്ന് structured ആയ, purged ആയ ഒരു form-ലേക്ക് data clean ചെയ്യുന്നതിനെ munging എന്ന് Wikipedia define ചെയ്യുന്നു. \ No newline at end of file