In this notebook, we will go over simple techniques in Python and Matplotlib that you can use to generate graphs that will help you in analyzing the ESG!
First on our agenda is to import dependencies -- or packages in Python that add to the basic functions in Python. Kind of like accessorizing! For example, matplotlib
allows us to generate the graphs we will be using.
The format is as follows: from (package) import (stuff)
, where the "stuff" we're importing can range from a specific function in that package to a whole library of functions, as is the case when we type import (package) as (name)
.
from datascience import *
import matplotlib.pyplot as plt
%matplotlib inline
import numpy as np
import pandas as pd
Please help us better establish the audience that we are reaching by filling out the following form:
insert link here!
Python is the programming language that we will use in this lab. Although this lab will go over some basics, should you be more interested in learning Python feel free to check out the following resources:
Mathematical Expressions In Python, we can carry out all the mathematical processes you know and love:
+
-
*
/
**
//
%
The most of these you should be familiar with, but let's go over some of the more obscure processes while beginning to implement some python code!
To submit the following cells and run the code, press Shift + Enter/Return!
# So what exactly does floor divide do?
10 // 3
3
# What about modulo?
10 % 3
1
Very cool! Now we'll let you try, and notice that we can use parentheses to organize our order of operations.
Exercise: Take the product of three and three to the power of six and subtract 169.
# Insert your code where the dots are:
...
Awesome job! Feel free to add more cells using the + button in the upper left hand corner of the lab and play around with more mathematical expressions later! In the meantime, let's move on to the next section.
As you might recall, a name that is used to denote a value is called a variable. In python, variables can be declared and values can be assigned. Here are a few examples of variables and their assignment:
x = 2
m = 3
b = 4
y = m*x + b
# Look familiar? Press shift + enter to see the value!
y
10
Output and Printing
As you might have noticed at the end, there is a difference between returning and printing:
We print using a print function and return a value using the return function.
Functions?
You might recall that a function receives input and correspondingly will output something. In Python, we have numerous functions, such as:
print
: The command print('hi')
will print 'hi' out to the screen.sum
: The command sum(2,3,4)
will sum up the values enclosed in the parentheses and return the value.The best thing about functions is that, in Python, we can make our own functions! We will discuss this more in depth later, but for now just remember that to call a function, we write the name of the function, like print()
and we place our arguments inside the parentheses.
Let's try it for ourselves!
Exercise: Try printing out the phrase 'Hello World!'
...
Ellipsis
A function is a block of organized, reusable code that is used to perform a single, related action. Take for example a factorial, denoted x!
, which takes the initial value x
and multiplies it by x-1
and x-2
and so on and so forth until it gets to 1! Typing this all out would look something like this:
# Let's pick a random value for x:
x = 5
factorial = 5 * 4 * 3 * 2 * 1
factorial
120
This might not seem too troublesome now, but imagine doing this by hand for a larger number like 12,345! Instead, let's consider writing a function that can take in any value (such as 12,345) and output the factorial!
Function Structure
So how can we begin writing a function? Well there is a very simple structure to them:
def function_name(arguments):
[function procedures]
return [output]
There are some aspects of a function that are required no matter what kind of function you are writing. You will always begin writing a function by writing def, followed by the name of your function. Following the name of your function, you will want to specify your inputs by using parentheses and giving your inputs names. These names can be anything you'd like, but generally you'd like them to be memorable and symbolic of what you're trying to do.
Before typing in your functions procedure in the body of your function, you'll want to end the first line with a :
. Then you're ready to proceed to the body and second line of your function! You will want to indent (press tab or space 4 times) and write what you'd like your function to do.
Lastly, you'll want to end the function by writing what you'd like your function to return.
Example: Let's look at what a factorial function would look like!
def factorial_func(x):
product = 1
while x > 0:
product = product * x
x = x - 1
return product
# Now let's test out our new factorial function!
factorial_func(5)
120
# Try calculating the factorial value for the crazy big number from before!
factorial_func(12345)
Amazing! However, you might have noticed there were some new features used, which brings us to our next small topic.
Loops
Something that came in handy for this equation was a loop. A loop is a piece of code that repeats a block of code while a condition is true or for a certain number of times. Like we just not-so-subtly hinted, there are two very important kinds of loops: for loops and while loops. In the case of our function above, the code under the while loop was repeated while x > 0
. On the other hand, a for loop will continue looping for a specified number of times.
So now that we know how to calculate things and create functions to do so, how can we organize large amounts of information?
The solution to our problem is a data structure! A data structures is simply a means by which to contain and organize our data or information. They include:
Here is how we can use lists:
# Creating a list using brackets and commas in between:
names = ['Helen', 'Nadeem', 'Alma', 'Nika']
names
['Helen', 'Nadeem', 'Alma', 'Nika']
# The first name in our list, located at position 0:
names[0]
'Helen'
# Adding a name, feel free to change the name to yours!
names.append('Sam')
names
['Helen', 'Nadeem', 'Alma', 'Nika', 'Sam']
Exercise: Now you try creating a list with the names of some of your friends or pets!
# Create your list below:
...
In addition to the data structures listed above, we can also organize our information in a table. Similar to Google Sheets or Microsoft Excel, we will be organzing our data into nice-looking tables. Let's get crackin'!
#####################SEPARATOR######################
ESG_table = Table.read_table('ESGPorfolios_forcsv.csv')
ESG_sorted = ESG_table.sort("Total_Var_Cost_USDperMWH")
4
ESG_sorted
Group | Group_num | UNIT NAME | Capacity_MW | Heat_Rate_MMBTUperMWh | Fuel_Price_USDperMMBTU | Fuel_Cost_USDperMWH | Var_OandM_USDperMWH | Total_Var_Cost_USDperMWH | Carbon_tonsperMWH | FixedCst_OandM_perDay | Unnamed: 11 | Unnamed: 12 | Unnamed: 13 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Old Timers | 7 | BIG CREEK | 1000 | nan | 0 | 0 | 0 | 0 | 0 | $15,000 | nan | nan | nan |
Fossil Light | 8 | HELMS | 800 | nan | 0 | 0 | 0.5 | 0.5 | 0 | $15,000 | nan | nan | nan |
Fossil Light | 8 | DIABLO CANYON 1 | 1000 | 1 | 7.5 | 7.5 | 4 | 11.5 | 0 | $20,000 | nan | nan | nan |
Bay Views | 4 | MOSS LANDING 6 | 750 | 6.9 | 4.5 | 31.06 | 1.5 | 32.56 | 0.37 | $8,000 | nan | nan | nan |
Bay Views | 4 | MOSS LANDING 7 | 750 | 6.9 | 4.5 | 31.06 | 1.5 | 32.56 | 0.37 | $8,000 | nan | nan | nan |
Old Timers | 7 | MOHAVE 1 | 750 | 10 | 3 | 30 | 4.5 | 34.5 | 0.94 | $15,000 | nan | nan | nan |
Old Timers | 7 | MOHAVE 2 | 750 | 10 | 3 | 30 | 4.5 | 34.5 | 0.94 | $15,000 | nan | nan | nan |
Big Coal | 1 | FOUR CORNERS | 1900 | 11.67 | 3 | 35 | 1.5 | 36.5 | 1.1 | $8,000 | nan | nan | nan |
Bay Views | 4 | MORRO BAY 3&4 | 665 | 8.02 | 4.5 | 36.11 | 0.5 | 36.61 | 0.43 | $4,000 | nan | nan | nan |
East Bay | 6 | PITTSBURGH 5&6 | 650 | 8.02 | 4.5 | 36.11 | 0.5 | 36.61 | 0.43 | $2,500 | nan | nan | nan |
... (32 rows omitted)
Big_Coal= ESG_sorted.where("Group","Big Coal")
Big_Coal
width_coal = Big_Coal.column("Capacity_MW")
width_coal
height_coal = Big_Coal.column("Total_Var_Cost_USDperMWH")
height_coal
array([ 36.5 , 40.5 , 41.94, 41.94, 66.5 , 73.72])
"""
Given widths sorted in ascending order, returns the y_positions used to graph the capacity vs variable costs bar graph
"""
def find_y_pos(widths):
cumulative_widths = [0]
cumulative_widths.extend(np.cumsum(widths))
half_widths = [i/2 for i in widths]
y_pos = []
for i in range(0, len(half_widths)):
y_pos.append(half_widths[i] + cumulative_widths[i])
return y_pos
new_y_coal = find_y_pos(width_coal)
new_y_coal
[950.0, 2050.0, 2375.0, 3025.0, 3575.0, 3775.0]
# Make the plot
plt.bar(new_y_coal, height_coal, width=width_coal)
#plt.xticks(y_pos, bars)
# Add title and axis names
plt.title('Big Coal')
plt.xlabel('Capacity_MW')
plt.ylabel('Variable Cost')
plt.show()
width = ESG_sorted.column("Capacity_MW")
width
height = ESG_sorted.column("Total_Var_Cost_USDperMWH")
height
array([ 0. , 0.5 , 11.5 , 32.56, 32.56, 34.5 , 34.5 , 36.5 , 36.61, 36.61, 38.06, 38.06, 38.78, 39.06, 39.5 , 40.5 , 40.94, 41.22, 41.67, 41.94, 41.94, 42.39, 42.67, 43.83, 44.83, 47.44, 49.17, 49.61, 52.06, 52.5 , 53.94, 58.28, 59.72, 61.17, 62.89, 65.5 , 66.5 , 69.83, 73.72, 75.61, 75.89, 90.06])
new_y = find_y_pos(width)
new_y
[500.0, 1400.0, 2300.0, 3175.0, 3925.0, 4675.0, 5425.0, 6750.0, 8032.5, 8690.0, 9365.0, 10065.0, 10582.5, 10900.0, 11400.0, 11900.0, 12375.0, 13025.0, 13825.0, 14475.0, 15125.0, 15925.0, 16675.0, 17450.0, 18000.0, 18275.0, 18425.0, 18575.0, 18725.0, 19075.0, 19400.0, 19525.0, 19950.0, 20375.0, 20525.0, 20675.0, 20825.0, 20975.0, 21175.0, 21450.0, 21725.0, 21950.0]
# Make the plot
plt.bar(new_y, height, width=width)
#plt.xticks(y_pos, bars)
# Add title and axis names
plt.title('All Energy Sources')
plt.xlabel('Capacity_MW')
plt.ylabel('Variable Cost')
plt.show()
energy_colors_dict = {}
count = 0
colors = ['b', 'g', 'r', 'c', 'm', 'y', 'k']
for i in set(ESG_sorted['Group']):
energy_colors_dict[i] = colors[count]
count += 1
colors_mapped = list(pd.Series(ESG_sorted['Group']).map(energy_colors_dict))
ESG_sorted = ESG_sorted.with_column('Color', colors_mapped)
# Make the plot
plt.bar(new_y, height, width=width, color=ESG_sorted['Color'])
#plt.xticks(y_pos, bars)
# Add title and axis names
plt.title('All Energy Sources')
plt.xlabel('Capacity_MW')
plt.ylabel('Variable Cost')
plt.show()
#set capacity here
capacity = 20000
price = 0
def price_calc(capacity, sorted_table):
sum_cap = 0
for i in range(0,len(sorted_table['Capacity_MW'])):
if sum_cap + sorted_table['Capacity_MW'][i] > capacity:
global price
price = sorted_table['Total_Var_Cost_USDperMWH'][i]
break
else:
sum_cap += sorted_table['Capacity_MW'][i]
def price_line_plot():
global price
plt.axhline(y=price, color='r', linewidth = 2)
print("Price: " + str(price))
def capacity_plot():
global capacity
plt.axvline(x=capacity, color='r', linewidth = 2)
print("Capacity: " + str(capacity))
*With Lines for price and quantity
# Make the plot
plt.bar(new_y, height, width=width, color=ESG_sorted['Color'])
#plt.xticks(y_pos, bars)
# Add title and axis names
plt.title('All Energy Sources')
plt.xlabel('Capacity_MW')
plt.ylabel('Variable Cost')
price_calc(capacity,ESG_sorted)
price_line_plot()
capacity_plot()
plt.show()
Price: 59.72 Capacity: 20000
# Make the plot
plt.bar(new_y_coal, height_coal, width=width_coal)
#plt.xticks(y_pos, bars)
# Add title and axis names
plt.title('Big Coal')
plt.xlabel('Capacity_MW')
plt.ylabel('Variable Cost')
price_line_plot()
plt.show()
Price: 59.72
sum(Big_Coal.where("Total_Var_Cost_USDperMWH", are.below(price))["Total_Var_Cost_USDperMWH"])
160.88
def profit(sorted_table):
global price
global capacity
capacity_subset = sum(sorted_table.where("Total_Var_Cost_USDperMWH", are.below(price))["Capacity_MW"])
revenue = capacity_subset * price
cost = sum(sorted_table.where("Total_Var_Cost_USDperMWH", are.below(price))["Total_Var_Cost_USDperMWH"])
return revenue - cost
profit(Big_Coal)
208859.12