Skip to content

Commit fe3193c

Browse files
committed
Updated: PfBA
1 parent 6085c4b commit fe3193c

11 files changed

Lines changed: 592 additions & 634 deletions

File tree

Python for Business Analysts/Automate Repetitive Tasks/ART_template.html

Lines changed: 162 additions & 167 deletions
Large diffs are not rendered by default.

Python for Business Analysts/Automate Repetitive Tasks/ART_template.ipynb

Lines changed: 120 additions & 166 deletions
Large diffs are not rendered by default.

Python for Business Analysts/Automate Repetitive Tasks/ART_template.md

Lines changed: 94 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11

2+
3+
```python
4+
from __future__ import print_function
5+
```
6+
27
#Python for Business Analysts
38

49
##Automate Repetitive Tasks
@@ -16,9 +21,58 @@ Create 2 variables, housing_2007 and housing_2005, that contain the DataFrame ob
1621
import pandas
1722

1823
housing_2007 = pandas.read_csv("data/Hud_2007.csv")
24+
print("housing_2007:\n", housing_2007.head(3))
25+
1926
housing_2005 = pandas.read_csv("data/Hud_2005.csv")
27+
print("housing_2005:\n", housing_2005.head(3))
2028
```
2129

30+
housing_2007:
31+
CONTROL AGE1 BEDRMS PER REGION LMED FMR L30 L50 L80 \
32+
0 '100003130103' -9 3 -6 '1' 66440 1048 14344 23890 37385
33+
1 '100003130203' 69 3 1 '1' 66440 1048 14344 23890 37385
34+
2 '100006110249' 45 3 1 '3' 49575 757 10893 18140 29019
35+
36+
... FMTINCRELFMRCAT FMTCOST06RELAMICAT FMTCOST08RELAMICAT \
37+
0 ... '.' '3 50 - 60% AMI' '4 60 - 80% AMI'
38+
1 ... '3 GT FMR' '1 LTE 30% AMI' '1 LTE 30% AMI'
39+
2 ... '2 50.1 - 100% FMR' '4 60 - 80% AMI' '5 80 - 100% AMI'
40+
41+
FMTCOST12RELAMICAT FMTCOSTMEDRELAMICAT FMTINCRELAMICAT FMTASSISTED \
42+
0 '5 80 - 100% AMI' '3 50 - 60% AMI' '.' '.'
43+
1 '1 LTE 30% AMI' '1 LTE 30% AMI' '6 100 - 120% AMI' '.'
44+
2 '6 100 - 120% AMI' '4 60 - 80% AMI' '4 60 - 80% AMI' '.'
45+
46+
FMTBURDEN FMTREGION FMTSTATUS
47+
0 '.' '-5' '-5'
48+
1 '1 Less than 30%' '-5' '-5'
49+
2 '2 30% to 50%' '-5' '-5'
50+
51+
[3 rows x 99 columns]
52+
housing_2005:
53+
CONTROL AGE1 BEDRMS PER REGION LMED FMR L30 L50 L80 \
54+
0 '100006110249' 43 3 1 '3' 47954 680 10359 17263 27615
55+
1 '100006370140' 44 4 5 '3' 47954 760 15988 26630 42607
56+
2 '100006520140' 58 3 3 '3' 47954 680 13321 22194 35506
57+
58+
... FMTINCRELFMRCAT FMTCOST06RELAMICAT FMTCOST08RELAMICAT \
59+
0 ... '2 50.1 - 100% FMR' '4 60 - 80% AMI' '4 60 - 80% AMI'
60+
1 ... '3 GT FMR' '5 80 - 100% AMI' '5 80 - 100% AMI'
61+
2 ... '3 GT FMR' '6 100 - 120% AMI' '7 120% AMI +'
62+
63+
FMTCOST12RELAMICAT FMTCOSTMEDRELAMICAT FMTINCRELAMICAT FMTASSISTED \
64+
0 '5 80 - 100% AMI' '4 60 - 80% AMI' '3 50 - 60% AMI' '.'
65+
1 '7 120% AMI +' '5 80 - 100% AMI' '7 120% AMI +' '.'
66+
2 '7 120% AMI +' '6 100 - 120% AMI' '7 120% AMI +' '.'
67+
68+
FMTBURDEN FMTREGION FMTSTATUS
69+
0 '3 Greater than 50%' '-5' '-5'
70+
1 '1 Less than 30%' '-5' '-5'
71+
2 '1 Less than 30%' '-5' '-5'
72+
73+
[3 rows x 99 columns]
74+
75+
2276
###2: Lists
2377

2478
Now that we have read in both datasets into DataFrame objects, let's add them to a List. A List is type of object (just like a DataFrame, Integer, or String) that contains an ordered group of objects. Just like how a grocery list contains a group of "ingredient" objects to buy, is a List object in Python houses a group of the objects we add to it. Instead of writing code to manipulate each object separately (in our case the objects are DataFrames), we can group a few objects into a List object, write the logic once, and apply it to every object in that List. This saves us a lot of time and energy, and will be important when we deal with much larger datasets with tens, hundreds or even thousands of DataFrames.
@@ -27,13 +81,13 @@ In the following code block, we will create an empty List called data_frames_lis
2781

2882
Then, we will add a year column for each DataFrame to keep track of which DataFrame is which:
2983

30-
housing_2005['year'] = '2005'
31-
housing_2007['year'] = '2007'
84+
housing_2005['year'] = '2005'
85+
housing_2007['year'] = '2007'
3286

3387
Each row now has a value for year, either 2005 or 2007, identifying which dataset that row originated from. Finally, we will use .append() to first add housing_2005 then housing_2007 to the end of data_frames_list. The List object preserves the order by which the DataFrames were added:
3488

35-
data_frames_list.append(housing_2005)
36-
data_frames_list.append(housing_2007)
89+
data_frames_list.append(housing_2005)
90+
data_frames_list.append(housing_2007)
3791

3892
The list now contains these two DataFrames in the order we added them.
3993

@@ -51,10 +105,10 @@ data_frames_list.append(housing_2005)
51105
data_frames_list.append(housing_2007)
52106

53107
# List now contains 2 objects, the respective dataframes for 2005 and 2007.
54-
print len(data_frames_list)
108+
print("data_frames_list:", len(data_frames_list))
55109
```
56110

57-
2
111+
data_frames_list: 2
58112

59113

60114
###3: Column Filtering
@@ -78,10 +132,11 @@ columns = ['AGE1', 'FMR', 'TOTSAL', 'year']
78132
# Filter dataframe.
79133
filtered_housing_2007 = housing_2007[columns]
80134

81-
print filtered_housing_2007[:5]
135+
print("filtered_housing_2007:\n", filtered_housing_2007[:5])
82136
```
83137

84-
AGE1 FMR TOTSAL year
138+
filtered_housing_2007:
139+
AGE1 FMR TOTSAL year
85140
0 -9 1048 -9 2007
86141
1 69 1048 0 2007
87142
2 45 757 26000 2007
@@ -127,23 +182,23 @@ to iterate over all of the object in data_frames_list (which contained our twp D
127182

128183
Instead of hard coding the columns we want at the filter level like we did in the last lesson:
129184

130-
filtered_housing_2013 = housing_2013[[ 'AGE1', 'FMR', 'TOTSAL', 'year' ]]
185+
filtered_housing_2013 = housing_2013[[ 'AGE1', 'FMR', 'TOTSAL', 'year' ]]
131186

132187
we assigned the column names to a list object, called columns:
133188

134-
columns = ['AGE1', 'FMR', 'TOTSAL', 'year']
189+
columns = ['AGE1', 'FMR', 'TOTSAL', 'year']
135190

136191
and passed it into the filter criteria:
137192

138-
filtered_df = df[columns]
193+
filtered_df = df[columns]
139194

140195
Instead of creating two different DataFrame objects (like filtered_housing_2005, filtered_housing_2007, etc), we created an empty list called new_df_list:
141196

142-
new_df_list = list()
197+
new_df_list = list()
143198

144199
and appended each of the filtered_df objects to it:
145200

146-
new_df_list.append(filtered_df)
201+
new_df_list.append(filtered_df)
147202

148203
As you can see, we placed a heavy emphasis on abstracting, or generalizing, our logic so we can detail the logic once, and apply it in many cases. The filter_columns function that we wrote is essentially a piece of software that will filter any list of DataFrame objects into the 4 columns we want. Whether the list of DataFrame objects has 1 DataFrame object or 25, the same function can be applied to get the result we want. Another abstraction we could implement would be to modify the function and specify the columns we want filtered every time by adding it as an input to the function (alongside data_frames_list). This way, instead of always using a specific set of columns within the function, the user can now specify in the input which columns they prefer to filter their DataFrames.
149204

@@ -158,11 +213,11 @@ Let's quickly verify that each of the DataFrame objects in filtered_data_frames_
158213
# For every dataframe in the list 'filtered_data_frames_list'.
159214
for df in filtered_data_frames_list:
160215
# Print dataframe columns.
161-
print df.columns
216+
print("df.columns:", df.columns)
162217
```
163218

164-
Index([u'AGE1', u'FMR', u'TOTSAL', u'year'], dtype='object')
165-
Index([u'AGE1', u'FMR', u'TOTSAL', u'year'], dtype='object')
219+
df.columns: Index(['AGE1', 'FMR', 'TOTSAL', 'year'], dtype='object')
220+
df.columns: Index(['AGE1', 'FMR', 'TOTSAL', 'year'], dtype='object')
166221

167222

168223
###7: Summary
@@ -175,7 +230,7 @@ Now let's write a function that counts the number of rows in each DataFrame that
175230

176231
In the following code block:
177232

178-
print( str(year) + " - " + str(len( negative_age_count ) ) + " rows")
233+
print( str(year) + " - " + str(len( negative_age_count ) ) + " rows")
179234

180235
we use the function str() to convert Integer objects, like year and len(negative_age_count), into String objects. The print function can only print String objects, so we must convert other objects to String objects. While not all objects can be converted to String objects for displaying, most can and we will cover in a later lesson how we can tell.
181236

@@ -188,7 +243,7 @@ for df in filtered_data_frames_list:
188243
# Return rows with negative age values.
189244
negative_age_count = df[df['AGE1']<0]
190245
# Print row count.
191-
print str(year) + " - " + str(len( negative_age_count ) ) + " rows"
246+
print(str(year) + " - " + str(len( negative_age_count ) ) + " rows")
192247
```
193248

194249
2005 - 3493 rows
@@ -209,15 +264,15 @@ Now let's write a function clean_rows() that takes a List of DataFrames and retu
209264

210265
Inside the function, we will first instantiate, or create, an empty list with no elements:
211266

212-
cleaned_list = list()
267+
cleaned_list = list()
213268

214269
Then, we will iterate through each DataFrame in filtered_data_frames_list, create a temporary DataFrame cleaned_df containing just the positive AGE1 rows for each DataFrame:
215270

216-
cleaned_df = df[ df ['AGE1'] > 0 ]
271+
cleaned_df = df[ df ['AGE1'] > 0 ]
217272

218273
And then we will append cleaned_df to cleaned_list for each iteration:
219274

220-
cleaned_list.append(cleaned_df)
275+
cleaned_list.append(cleaned_df)
221276

222277
Let's run this function clean_rows on data_frames_list and assign the results to cleaned_data_frames_list.
223278

@@ -237,136 +292,24 @@ def clean_rows(filtered_data_frames_list):
237292

238293
cleaned_data_frames_list = clean_rows(filtered_data_frames_list)
239294

240-
print cleaned_data_frames_list
295+
print("cleaned_data_frames_list[0]:\n", cleaned_data_frames_list[0][:5])
296+
print("cleaned_data_frames_list[1]:\n", cleaned_data_frames_list[1][:5])
241297
```
242298

243-
[ AGE1 FMR TOTSAL year
244-
0 43 680 20000 2005
245-
1 44 760 71000 2005
246-
2 58 680 63000 2005
247-
3 22 519 27040 2005
248-
4 48 600 14000 2005
249-
5 42 788 42000 2005
250-
7 23 546 48000 2005
251-
8 51 680 58000 2005
252-
9 47 1081 125000 2005
253-
10 66 1081 0 2005
254-
11 47 1006 54400 2005
255-
12 30 874 439364 2005
256-
13 49 916 75000 2005
257-
14 60 972 0 2005
258-
15 47 862 80000 2005
259-
16 59 629 550 2005
260-
17 45 862 42000 2005
261-
18 54 607 65000 2005
262-
19 35 892 57000 2005
263-
21 33 972 58000 2005
264-
22 42 760 59050 2005
265-
23 37 963 44000 2005
266-
24 52 879 136000 2005
267-
26 27 750 42500 2005
268-
27 54 1035 5000 2005
269-
28 37 833 2000 2005
270-
29 52 940 77883 2005
271-
30 70 1080 0 2005
272-
31 82 1017 0 2005
273-
32 46 1168 14000 2005
274-
... ... ... ... ...
275-
46821 27 677 62000 2005
276-
46822 53 972 0 2005
277-
46823 42 1267 95000 2005
278-
46824 47 1190 53200 2005
279-
46825 28 1397 91000 2005
280-
46826 23 677 30000 2005
281-
46828 84 817 0 2005
282-
46829 36 1168 79919 2005
283-
46830 30 1607 82000 2005
284-
46831 54 1094 54000 2005
285-
46832 46 1190 79000 2005
286-
46833 46 1168 48000 2005
287-
46834 58 817 42500 2005
288-
46835 62 1168 124000 2005
289-
46836 56 1420 82000 2005
290-
46837 34 1420 103000 2005
291-
46838 41 1168 52000 2005
292-
46839 56 1607 85000 2005
293-
46840 30 825 24000 2005
294-
46841 60 825 100000 2005
295-
46842 46 693 46500 2005
296-
46843 28 825 50000 2005
297-
46844 26 1397 61000 2005
298-
46845 23 1190 57000 2005
299-
46846 34 1633 200000 2005
300-
46847 46 1168 302000 2005
301-
46848 33 1168 105000 2005
302-
46849 40 1397 65000 2005
303-
46850 44 1397 280400 2005
304-
46852 44 1420 75000 2005
305-
306-
[43360 rows x 4 columns], AGE1 FMR TOTSAL year
307-
1 69 1048 0 2007
308-
2 45 757 26000 2007
309-
3 47 847 126000 2007
310-
4 30 616 42000 2007
311-
5 50 605 15000 2007
312-
6 44 807 145000 2007
313-
8 24 599 96000 2007
314-
9 53 757 85000 2007
315-
10 49 974 165000 2007
316-
11 44 974 71000 2007
317-
12 61 956 104000 2007
318-
13 29 572 0 2007
319-
14 21 572 25000 2007
320-
15 49 1097 93000 2007
321-
16 31 871 485968 2007
322-
17 51 900 53500 2007
323-
18 49 930 90000 2007
324-
19 61 930 0 2007
325-
20 45 930 0 2007
326-
21 53 923 150000 2007
327-
22 56 818 125000 2007
328-
23 20 583 12000 2007
329-
24 48 1169 200000 2007
330-
25 34 1042 81000 2007
331-
26 44 847 70000 2007
332-
27 39 961 55000 2007
333-
28 54 882 130000 2007
334-
29 46 948 150000 2007
335-
30 50 951 50000 2007
336-
32 24 700 55000 2007
337-
... ... ... ... ...
338-
42696 71 1010 0 2007
339-
42697 19 896 100 2007
340-
42698 36 1278 96000 2007
341-
42700 47 1097 80400 2007
342-
42701 44 1147 116000 2007
343-
42702 65 896 90000 2007
344-
42703 45 1784 80000 2007
345-
42704 33 1359 176000 2007
346-
42705 50 648 44000 2007
347-
42706 55 1042 0 2007
348-
42707 49 1139 48000 2007
349-
42708 21 648 10000 2007
350-
42710 38 1278 32000 2007
351-
42711 34 1470 100002 2007
352-
42712 44 1169 162000 2007
353-
42713 48 1139 25000 2007
354-
42714 48 1278 74100 2007
355-
42715 65 1278 87000 2007
356-
42716 58 1359 120000 2007
357-
42717 67 963 0 2007
358-
42718 58 1517 0 2007
359-
42719 65 1517 0 2007
360-
42721 35 1517 12000 2007
361-
42722 24 1359 60000 2007
362-
42723 48 1278 310000 2007
363-
42724 57 1278 40800 2007
364-
42725 42 1517 94000 2007
365-
42726 46 1517 185000 2007
366-
42727 25 782 0 2007
367-
42728 45 1310 90000 2007
368-
369-
[39107 rows x 4 columns]]
299+
cleaned_data_frames_list[0]:
300+
AGE1 FMR TOTSAL year
301+
0 43 680 20000 2005
302+
1 44 760 71000 2005
303+
2 58 680 63000 2005
304+
3 22 519 27040 2005
305+
4 48 600 14000 2005
306+
cleaned_data_frames_list[1]:
307+
AGE1 FMR TOTSAL year
308+
1 69 1048 0 2007
309+
2 45 757 26000 2007
310+
3 47 847 126000 2007
311+
4 30 616 42000 2007
312+
5 50 605 15000 2007
370313

371314

372315
###11: Verify Cleanup
@@ -392,10 +335,10 @@ def verify_cleanup(data_frames_list):
392335
verification_count = -1
393336
verification_count = verify_cleanup(cleaned_data_frames_list)
394337

395-
print verification_count
338+
print("verification_count:", verification_count)
396339
```
397340

398-
0
341+
verification_count: 0
399342

400343

401344
###12: Summary

0 commit comments

Comments
 (0)