From 1cfa465190915ccee8a1972d616b9ff83698b293 Mon Sep 17 00:00:00 2001 From: Maxsmith22 <166277426+Maxsmith22@users.noreply.github.com> Date: Sat, 6 Apr 2024 23:50:58 -0600 Subject: [PATCH] Add files via upload --- docs/Max Smith Resume 2024.pdf | Bin 0 -> 78031 bytes docs/project_0.qmd | 102 ++++++++++ docs/project_1.qmd | 214 +++++++++++++++++++++ docs/project_2.qmd | 314 +++++++++++++++++++++++++++++++ docs/project_3.qmd | 216 +++++++++++++++++++++ docs/project_4.qmd | 229 +++++++++++++++++++++++ docs/project_5.qmd | 332 +++++++++++++++++++++++++++++++++ 7 files changed, 1407 insertions(+) create mode 100644 docs/Max Smith Resume 2024.pdf create mode 100644 docs/project_0.qmd create mode 100644 docs/project_1.qmd create mode 100644 docs/project_2.qmd create mode 100644 docs/project_3.qmd create mode 100644 docs/project_4.qmd create mode 100644 docs/project_5.qmd diff --git a/docs/Max Smith Resume 2024.pdf b/docs/Max Smith Resume 2024.pdf new file mode 100644 index 0000000000000000000000000000000000000000..806459fdb04e663c9e79b7af8b8129960411e5a7 GIT binary patch literal 78031 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

lbq?A-FPC<`Qb`A|6@*_0-j-uDTRR0Tan6Kh)Kg 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 literal 0 HcmV?d00001 diff --git a/docs/project_0.qmd b/docs/project_0.qmd new file mode 100644 index 0000000..1703158 --- /dev/null +++ b/docs/project_0.qmd @@ -0,0 +1,102 @@ +--- +title: "Client Report - Introduction" +subtitle: "Course DS 250" +author: "Max Smith" +format: + html: + self-contained: true + page-layout: full + title-block-banner: true + toc: true + toc-depth: 3 + toc-location: body + number-sections: false + html-math-method: katex + code-fold: true + code-summary: "Show the code" + code-overflow: wrap + code-copy: hover + code-tools: + source: false + toggle: true + caption: See code +execute: + warning: false + +--- + +```{python} +#| label: libraries +#| include: false +import pandas as pd +import numpy as np +import plotly.express as px + +# the following for mac users ro download data through the Internet +import ssl +ssl._create_default_https_context = ssl._create_unverified_context +``` + + +## Elevator pitch + +In this analysis, we will take a look at a data set based on cars. In this data we have information like manufacturer, miles per gallon, engine size, and a couple others. We will be answering the question of whether a cars fuel efficiency gets better or worse as the engine size increases. In this report we will also see the top 5 rows in our data set. + +```{python} +#| label: project data +#| code-summary: Read and format project data + +df = pd.read_csv('mpg.csv') + +``` + +__Highlight the Questions and Tasks__ + +## QUESTION|TASK 1 + +Finish the readings and be prepared with any questions to get your environment working smoothly. + +Finished all readings. + + +## QUESTION|TASK 2 + +In VS Code, write a python script to create the example chart from section 3.2.2 of the textbook + +The graph provided shows the negative relationship between engine sizes and the vehicles mile per gallon. This tells us that as a cars engine gets bigger, the cars mpg decreases. There is a small group of semi-outliers with bigger engines that have slightly better than average mpg, however it is still only comparable to the cars with the smallest engines that have the worst mpg. + +_include figures in chunks and discuss your findings in the figure._ + +```{python} +#| label: Q2 chart +#| code-summary: plot example +#| fig-cap: "My useless chart" +#| fig-align: center +# Include and execute your code here + +chart = px.scatter(df, + x="displ", + y="hwy" +) +chart.show() +``` + + +## QUESTION|TASK 3 + +Your final report should also include the markdown table created from the following + +From this table, we can see that the top 5 cars in the table are audi a4s varying in year and hwy. This tells us that the table is most likely alphabetically sorted by manufacturer. + +```{python} +#| label: Q3 table +#| code-summary: table example +#| tbl-cap: "Not much of a table" +#| tbl-cap-location: top +# Include and execute your code here +print(df + .head(5) + .filter(["manufacturer", "model","year", "hwy"]) + .to_markdown(index=False)) + +``` diff --git a/docs/project_1.qmd b/docs/project_1.qmd new file mode 100644 index 0000000..7987345 --- /dev/null +++ b/docs/project_1.qmd @@ -0,0 +1,214 @@ +--- +title: "Client Report - [Insert Project Title]" +subtitle: "Course DS 250" +author: "[STUDENT NAME]" +format: + html: + self-contained: true + page-layout: full + title-block-banner: true + toc: true + toc-depth: 3 + toc-location: body + number-sections: false + html-math-method: katex + code-fold: true + code-summary: "Show the code" + code-overflow: wrap + code-copy: hover + code-tools: + source: false + toggle: true + caption: See code +execute: + warning: false + +--- + +```{python} +#| label: libraries +#| include: false +import pandas as pd +import numpy as np +import plotly.express as px + +# the following for mac users ro download data through the Internet +import ssl +ssl._create_default_https_context = ssl._create_unverified_context +``` + + +## Elevator pitch + +In this analysis you will find specific insights of my name, the name 'Brittany', biblical names, and even the affects a popular movie had on naming children. I have provided visuals to easily see the change in activity of all of these names over the years. I also have provided short analysis before each of the charts to help explain what is exactly going on in the graph. + +```{python} +#| label: project data +#| code-summary: Read and format project data +# Include and execute your code here +df = pd.read_csv("https://raw.githubusercontent.com/byuidatascience/data4names/master/data-raw/names_year/names_year.csv") + + +``` + +__Highlight the Questions and Tasks__ + +## QUESTION|TASK 1 + +How does your name at your birth year compare to its use historically? + +It seems like my name 'Max' has never been more popular than during my lifetime. It looks like the name was on a downward trend until 1983 and the name became more and more popular. It even looked like my name was starting to decline in popularity, but the year before I was born it caught traction again in 1998. + +```{python} +#| label: Q1 +#| code-summary: Read and format data +# Include and execute your code here + +max_df = df.query('name == "Max"') + +``` + + +```{python} +#| label: Q1 chart +#| code-summary: plot example +#| fig-cap: "My useless chart" +#| fig-align: center +# Include and execute your code here +max_chart = px.bar(max_df, + x='year', + y='Total', + title='The Name "Max"' +) +max_chart.add_vrect(x0=1999, x1=2016) + +max_chart.add_annotation(x=1999, y=3500, + text='My lifetime', + showarrow=True, + arrowhead=3, + arrowsize=2, + ax=-80, + ay=-10) + +max_chart.show() + +#max_utah = max_df['UT'].sum() +#max_utah + +``` + + + +## QUESTION|TASK 2 + +If you talked to someone named Brittany on the phone, what is your guess of his or her age? What ages would you not guess? + +From the graph we can assume that Brittany is about 34 years old, give or take 5 years. Before/after that the amount of people named Brittany fell significantly. I would not guess that she was born before 1984 or after 1999. + +```{python} +#| label: Q2 +#| code-summary: Read and format data +# Include and execute your code here + +brittany_df = df.query('name == "Brittany"') + + +#brittany_df['year'].median() +#brittany_df['year'].mean() + +``` + + +```{python} +#| label: Q2 chart +#| code-summary: plot example +#| fig-cap: "My useless chart" +#| fig-align: center +# Include and execute your code here +britt_chart = px.bar(brittany_df, + x="year", + y="Total", + title='The Name "Brittany"' +) +britt_chart.show() +``` + + + +## QUESTION|TASK 3 + +Mary, Martha, Peter, and Paul are all Christian names. From 1920 - 2000, compare the name usage of each of the four names. What trends do you notice? + +It seems like for all these biblical names, there is a significant fall off around the years 1954-1956 that has continued even until this day, just at a lesser rate. However all of the names seemed to peak right before the big decline in 1954-1956. + +```{python} +#| label: Q3 +#| code-summary: Read and format data +# Include and execute your code here + +christian_names = df.query('name=="Mary" or name=="Martha" or name=="Peter" or name=="Paul"') + +christian_names = christian_names.query('year >= 1920 and year <= 2000') + +``` + + +```{python} +#| label: Q3 chart +#| code-summary: plot example +#| fig-cap: "My useless chart" +#| fig-align: center +# Include and execute your code here +christian_chart = px.line(christian_names, + x='year', + y='Total', + color='name', + title='Biblical Names' +) +christian_chart.show() +``` + + +## QUESTION|TASK 4 + +Think of a unique name from a famous movie. Plot the usage of that name and see how changes line up with the movie release. Does it look like the movie had an effect on usage? + +I analyzed the name 'Elsa' from the movie Frozen, which was released in 2013. We can see from this graph that it wasn't a very common name until the movie was released. There is a very steep incline following the release of the movie, showing that there is a direct relationship with the movie release and people naming their kids 'Elsa'. + +```{python} +#| label: Q4 +#| code-summary: Read and format data +# Include and execute your code here + +movie_name = df.query('name=="Elsa"') + +movie_name = movie_name.query('year >= 2000 and year <= 2023') + +``` + + +```{python} +#| label: Q4 chart +#| code-summary: plot example +#| fig-cap: "My useless chart" +#| fig-align: center +# Include and execute your code here +movie_chart = px.line(movie_name, + x='year', + y='Total', + color='name', + title='The Name "Elsa" from Frozen' +) +#movie_chart.add_vline(x=2013) + +movie_chart.add_annotation(x=2013, y=525, + text='"Frozen" Movie Release', + showarrow=True, + arrowhead=3, + arrowsize=2, + ax=-80, + ay=-80) + +movie_chart.show() +``` + diff --git a/docs/project_2.qmd b/docs/project_2.qmd new file mode 100644 index 0000000..e6f20c0 --- /dev/null +++ b/docs/project_2.qmd @@ -0,0 +1,314 @@ +--- +title: "Client Report - Late flights and missing data" +subtitle: "Course DS 250" +author: "Max Smith" +format: + html: + self-contained: true + page-layout: full + title-block-banner: true + toc: true + toc-depth: 3 + toc-location: body + number-sections: false + html-math-method: katex + code-fold: true + code-summary: "Show the code" + code-overflow: wrap + code-copy: hover + code-tools: + source: false + toggle: true + caption: See code +execute: + warning: false + +--- + +```{python} +#| label: libraries +#| include: false +import pandas as pd +import numpy as np +import plotly.express as px + +# the following for mac users ro download data through the Internet +import ssl +ssl._create_default_https_context = ssl._create_unverified_context +``` + + +## Elevator pitch + +In this report we will take a look into data gathered from airports in the USA and will primarily focus on delays. We will analyze the delays by airport, month, and weather. We find in this data that Chicago averages the longest delays compared to the other airports. We also will see that September has the smallest proportion of delayed flights and San Fransisco has the highest proportion of delayed flights due to weather. + +```{python} +#| label: project data +#| code-summary: Read and format project data +# Include and execute your code here +df = pd.read_json('https://raw.githubusercontent.com/byuidatascience/data4missing/master/data-raw/flights_missing/flights_missing.json') + +``` + +__Highlight the Questions and Tasks__ + +## QUESTION|TASK 1 + +Fix all of the varied missing data types in the data to be consistent (all missing values should be displayed as “NaN”). In your report include one record example (one row) from your new data, in the raw JSON format. Your example should display the “NaN” for at least one missing value.__ + +In this data set I found missing values entered as empty, -999, and n/a. I was able to change all of these values to NaN in order to clean the data for further analysis. + +```{python} +#| label: Q1 +#| code-summary: Read and format data +# Include and execute your code here + +clean_df = df.replace(["", -999, "n/a"],np.nan) + +``` + +In this table we can see a values of NaN in the 'num_of_delays_late_aircraft' column. Prior to the data cleaning the value was -999. If left uncleaned it would ruin the data when performing math analysis on the column. + + +```{python} +#| label: Q1 table +#| code-summary: table example +#| tbl-cap: "Not much of a table" +#| tbl-cap-location: top +# Include and execute your code here +mydat = clean_df.head(1) + +display(mydat) + +``` + + +## QUESTION|TASK 2 + +Which airport has the worst delays? Discuss the metric you chose, and why you chose it to determine the “worst” airport. Your answer should include a summary table that lists (for each airport) the total number of flights, total number of delayed flights, proportion of delayed flights, and average delay time in hours. + +To figure out which airport had the worst delays I grouped the data by airport and measured them by the average delay time. I chose this metric because the highest average will be the airport that experiences the longest delays out of the total flights. + +```{python} +#| label: Q2 +#| code-summary: Read and format data +# Include and execute your code here + +# group by airport +airport_group = clean_df.groupby('airport_code').agg( + total_flights=pd.NamedAgg(column='num_of_flights_total', aggfunc='sum'), + total_delays=pd.NamedAgg(column='num_of_delays_total', aggfunc='sum'), + total_minutes_delayed=pd.NamedAgg(column='minutes_delayed_total', aggfunc='sum') +) + +# make a new column finding the proportion of delayed flights +airport_group['proportion_delayed_flights'] = airport_group['total_delays'] / airport_group['total_flights'] + +# new column of avg delay time +airport_group['avg_delay_time_hours'] = (airport_group['total_minutes_delayed'] / 60) / airport_group['total_delays'] + +airport_group = airport_group.filter(['total_flights', 'total_delays', 'proportion_delayed_flights', 'avg_delay_time_hours']) + +# reset the airport code column +airport_group = airport_group.reset_index() + +# sort table +airport_group = airport_group.sort_values('avg_delay_time_hours', ascending=False) +``` + +The graph shown below tells us that on average the Chicago, IL: Chicago O'Hare International (ORD) airport averages the longest delays at 1 hour and 8 minutes. On the other hand San Diego, CA: San Diego International (SAN) averages the shortest delays at 48 minutes. The table below is ordered by the highest average to smallest. + +```{python} +#| label: Q2 chart +#| code-summary: plot example +#| fig-cap: "My useless chart" +#| fig-align: center +# Include and execute your code here +chart = px.bar(airport_group, + x="airport_code", + y="avg_delay_time_hours", + title="Average Delay Time by Airport", + labels={"airport_code": "Airport Code", "avg_delay_time_hours": "Average Delay Time (Hours)"} +) +chart.show() +``` + + +```{python} +#| label: Q2 table +#| code-summary: table example +#| tbl-cap: "Not much of a table" +#| tbl-cap-location: top +# Include and execute your code here + +# I have to make the table for my graph so I have my code for the table two boxes up. + +display(airport_group) + +``` + + +## QUESTION|TASK 3 + +What is the best month to fly if you want to avoid delays of any length? Discuss the metric you chose and why you chose it to calculate your answer. Include one chart to help support your answer, with the x-axis ordered by month. (To answer this question, you will need to remove any rows that are missing the Month variable.) + +The month to fly that provides the best chance of aboiding a missed flight is in September. This was found by grouping the data by month and then finding the proportion of total flights by month that are delayed. This analysis shows us the likelyhood of having a delay for each month. + +```{python} +#| label: Q3 +#| code-summary: Read and format data +# Include and execute your code here + +clean_month_df = clean_df.dropna(subset=['month']) + +# group data by month +month_group = clean_month_df.groupby('month')[ + ['num_of_flights_total', + 'num_of_delays_total', + 'minutes_delayed_total' + ] +].agg('sum') + +# make a new porportion column and average column +month_group['proportion_delayed_flights'] = month_group['num_of_delays_total'] / month_group['num_of_flights_total'] + +month_group['avg_delay_time_hours'] = (month_group['minutes_delayed_total'] / 60) / month_group['num_of_delays_total'] + +month_group = month_group.filter(['num_of_flights_total', 'num_of_delays_total', 'proportion_delayed_flights', 'avg_delay_time_hours']) + +month_group = month_group.reset_index() + +month_group = month_group.sort_values('proportion_delayed_flights') + + + +``` + +September has a proportion of delayed flights of 16.45% of total flights. December has the worst proportion with 25.68% of flights are delayed. This could be a direct effect of seasonal weather like wind and snow. The table below is ordered by smallest proportion to highest. + +```{python} +#| label: Q3 chart +#| code-summary: plot example +#| fig-cap: "My useless chart" +#| fig-align: center +# Include and execute your code here +month_chart = px.bar(month_group, + x="month", + y="proportion_delayed_flights", + title="Proportion of Delayed Flights by Month", + labels={"month": "Month", "proportion_delayed_flights": "Proportion of Delayed Flights"} +) +month_chart.show() +``` + + +```{python} +#| label: Q3 table +#| code-summary: table example +#| tbl-cap: "Not much of a table" +#| tbl-cap-location: top +# Include and execute your code here + +display(month_group) + +``` + + +## QUESTION|TASK 4 + +According to the BTS website, the “Weather” category only accounts for severe weather delays. Mild weather delays are not counted in the “Weather” category, but are actually included in both the “NAS” and “Late-Arriving Aircraft” categories. Your job is to create a new column that calculates the total number of flights delayed by weather (both severe and mild). You will need to replace all the missing values in the Late Aircraft variable with the mean. Show your work by printing the first 5 rows of data in a table. Use these three rules for your calculations:__ + +100% of delayed flights in the Weather category are due to weather + +30% of all delayed flights in the Late-Arriving category are due to weather. + +From April to August, 40% of delayed flights in the NAS category are due to weather. The rest of the months, the proportion rises to 65%. + + + +Here is a table of all of the recquired information. The last column is the column that shows the total amount of delays due to weather by airport. + +```{python} +#| label: Q4 +#| code-summary: Read and format data +# Include and execute your code here + +#weather_df = clean_df.filter(['airport_code', 'month', 'num_of_delays_late_aircraft', 'num_of_delays_nas', 'num_of_delays_weather']) + +weather_df = clean_df + +# find the average number of delays of late aircraft +mean_num_weather = (weather_df['num_of_delays_late_aircraft']).mean().round(0) + +weather_df['num_of_delays_late_aircraft'] = weather_df['num_of_delays_late_aircraft'].replace([np.nan],mean_num_weather) + +nas_weather_related = np.where( + weather_df['month'].isin(['April', 'May', 'June', 'July', 'August']), + weather_df['num_of_delays_nas'] * 0.4, + weather_df['num_of_delays_nas'] * 0.65 +) + +weather_df['total_num_of_delays_weather'] = ( + weather_df['num_of_delays_weather'] + + (weather_df['num_of_delays_late_aircraft'] * 0.3) + + nas_weather_related +) + +``` + +Here are the top 5 rows of this table. + + +```{python} +#| label: Q4 table +#| code-summary: table example +#| tbl-cap: "Not much of a table" +#| tbl-cap-location: top +# Include and execute your code here + +weather_df.sort_values('total_num_of_delays_weather').head(5) + +``` + + +## QUESTION|TASK 5 + +Using the new weather variable calculated above, create a barplot showing the proportion of all flights that are delayed by weather at each airport. Discuss what you learn from this graph. + +This graph shows us the proportions of delays due to weather by each airport. It was interesting seeing that this graph was so different from the other graphs shown above. It really shows how weather is a whole different factor to the total amount of delays. + +```{python} +#| label: Q5 +#| code-summary: Read and format data +# Include and execute your code here + +# group by airport and make a new table with just the columns I want +airport_weather_delay = weather_df.groupby('airport_code')[ + ['num_of_flights_total', + 'total_num_of_delays_weather' + ] +].agg('sum') + +airport_weather_delay['weather_delay_proportion'] = airport_weather_delay['total_num_of_delays_weather'] / airport_weather_delay['num_of_flights_total'] + +airport_weather_delay = airport_weather_delay.reset_index() + +airport_weather_delay = airport_weather_delay.sort_values('weather_delay_proportion', ascending = False) +``` + + I amd surprised that SFO has the highest proportiong of delays due to weather. I would've thought California had better, more consistent weather. While SLC has the lowest proportiong, but they get so much snow and wind. + +```{python} +#| label: Q5 chart +#| code-summary: plot example +#| fig-cap: "My useless chart" +#| fig-align: center +# Include and execute your code here +weather_delay = px.bar(airport_weather_delay, + x="airport_code", + y="weather_delay_proportion", + title="Proportion of Delayed Flights by Weather by Airport", + labels={"month": "Airport", "weather_delay_proportion": "Proportion of Delayed Flights Due to Weather"} +) +weather_delay.show() +``` diff --git a/docs/project_3.qmd b/docs/project_3.qmd new file mode 100644 index 0000000..c5e304b --- /dev/null +++ b/docs/project_3.qmd @@ -0,0 +1,216 @@ +--- +title: "Client Report - Finding relationships in baseball." +subtitle: "Course DS 250" +author: "Max Smith" +format: + html: + self-contained: true + page-layout: full + title-block-banner: true + toc: true + toc-depth: 3 + toc-location: body + number-sections: false + html-math-method: katex + code-fold: true + code-summary: "Show the code" + code-overflow: wrap + code-copy: hover + code-tools: + source: false + toggle: true + caption: See code +execute: + warning: false + +--- + +```{python} +#| label: libraries +#| include: false +import pandas as pd +import numpy as np +import plotly.express as px +import sqlite3 + +# the following for mac users ro download data through the Internet +import ssl +ssl._create_default_https_context = ssl._create_unverified_context +``` + + +## Elevator pitch + +In this report we take a look at a baseball database. We query the database to find specific results such as players that played in the MLB and went to school at BYUI. We also worked on grouping the data and aggregating it. We also took a look into using the fields to make new fields by dividing them from one another. There is lots to learn in this report! + +```{python} +#| label: project-data +#| code-summary: Read and format project data + +# Learn morea about Code Cells: https://quarto.org/docs/reference/cells/cells-jupyter.html + +# Include and execute your code here +sqlite_file = 'lahmansbaseballdb.sqlite' +con = sqlite3.connect(sqlite_file) +``` + +__Highlight the Questions and Tasks__ + +## QUESTION|TASK 1 + +Write an SQL query to create a new dataframe about baseball players who attended BYU-Idaho. The new table should contain five columns: playerID, schoolID, salary, and the yearID/teamID associated with each salary. Order the table by salary (highest to lowest) and print out the table in your report. + + +```{python} +#| label: Q1 +#| code-summary: Read and format data +# Include and execute your code here + +byui_players = ''' + +SELECT sal.playerid, cp.schoolid, sal.salary, sal.yearid, sal.teamid +FROM collegeplaying as cp +JOIN salaries as sal ON cp.playerid = sal.playerid +WHERE cp.schoolid = 'idbyuid' +ORDER BY salary DESC + +''' +byui_results = pd.read_sql_query(byui_players,con) + +byui_results + +``` + + +## QUESTION|TASK 2 + +This three-part question requires you to calculate batting average (number of hits divided by the number of at-bats) + +- a. Write an SQL query that provides playerID, yearID, and batting average for players with at least 1 at bat that year. Sort the table from highest batting average to lowest, and then by playerid alphabetically. Show the top 5 results in your report. + +```{python} +#| label: Q2-a +#| code-summary: Read and format data +# Include and execute your code here + +batting_info_a = ''' + +SELECT playerid, yearid, (CAST(H AS REAL) / AB) as batting_avg +FROM batting +WHERE AB >= 1 +ORDER BY batting_avg DESC, playerid +LIMIT 5 + +''' +batting_results_a = pd.read_sql_query(batting_info_a,con) + +batting_results_a +``` + + +- b. Use the same query as above, but only include players with at least 10 at bats that year. Print the top 5 results. + + +```{python} +#| label: Q2-b +#| code-summary: Read and format data +# Include and execute your code here + +batting_info_b = ''' + +SELECT playerid, yearid, (CAST(H AS REAL) / AB) as batting_avg +FROM batting +WHERE AB >= 10 +ORDER BY batting_avg DESC, playerid +LIMIT 5 + +''' +batting_results_b = pd.read_sql_query(batting_info_b,con) + +batting_results_b +``` + +- c. Now calculate the batting average for players over their entire careers (all years combined). Only include players with at least 100 at bats, and print the top 5 results. + +```{python} +#| label: Q2-c +#| code-summary: Read and format data +# Include and execute your code here + +batting_info_c = ''' + +SELECT playerid, (CAST(SUM(H) AS REAL) / SUM(AB)) as career_batting_avg +FROM batting +GROUP BY playerid +HAVING SUM(AB) >= 100 +ORDER BY career_batting_avg DESC +LIMIT 5 + +''' +batting_results_c = pd.read_sql_query(batting_info_c,con) + +batting_results_c +``` + + +## QUESTION|TASK 3 + +Pick any two baseball teams and compare them using a metric of your choice (average salary, home runs, number of wins, etc). Write an SQL query to get the data you need, then make a graph using Plotly Express to visualize the comparison. What do you learn? + +I gathered two teams here. One with the best win to loss ratio and the other with the worst. we are comparing their salaries and seeing if that has an affect on their win to loss ratio. + +```{python} +#| label: Q3 +#| code-summary: Read and format data +# Include and execute your code here + +team_info = ''' + +SELECT t.name, SUM(salary) as total_salary, (CAST(SUM(W) AS REAL) /SUM(L)) AS 'win_loss_ratio' +FROM teams as t +JOIN salaries as s ON t.teamid = s.teamid +WHERE t.teamid IN ('NYA', 'MIA') +GROUP BY t.teamid +ORDER BY win_loss_ratio DESC + + +''' +team_results = pd.read_sql_query(team_info,con) + +team_results + +``` + +It is interesting because the New York Highlanders have a better W/L percentage and have a lot higher salary, so based off these two teams it looks like salary has an impact on the teams winning percentage! + +```{python} +#| label: Q3-chart +#| code-summary: plot example +#| fig-cap: "My useless chart" +#| fig-align: center +# Include and execute your code here +chart = px.bar(team_results, + x="win_loss_ratio", + y="total_salary", + color = 'name' +) +chart.show() +``` + + +```{python} +#| label: Q3-table +#| code-summary: table example +#| tbl-cap: "Not much of a table" +#| tbl-cap-location: top +# Include and execute your code here +# mydat = df.head(1000)\ +# .groupby('year')\ +# .sum()\ +# .reset_index()\ +# .tail(10)\ +# .filter(["year", "AK","AR"]) + +# display(mydat) + +``` diff --git a/docs/project_4.qmd b/docs/project_4.qmd new file mode 100644 index 0000000..000794b --- /dev/null +++ b/docs/project_4.qmd @@ -0,0 +1,229 @@ +--- +title: "Client Report - Project 4: Can you predict that?" +subtitle: "Course DS 250" +author: "Max Smith" +format: + html: + self-contained: true + page-layout: full + title-block-banner: true + toc: true + toc-depth: 3 + toc-location: body + number-sections: false + html-math-method: katex + code-fold: true + code-summary: "Show the code" + code-overflow: wrap + code-copy: hover + code-tools: + source: false + toggle: true + caption: See code +execute: + warning: false + +--- + +```{python} +#| label: libraries +#| include: false +import pandas as pd +import numpy as np +import plotly.express as px +from sklearn.tree import DecisionTreeClassifier # Import Decision Tree Classifier +from sklearn import metrics #Import scikit-learn metrics module for accuracy calculation +from sklearn.model_selection import train_test_split +from sklearn.naive_bayes import GaussianNB +from sklearn.ensemble import RandomForestClassifier +from sklearn.metrics import accuracy_score, confusion_matrix, precision_score, recall_score, f1_score + + +``` + + +## Elevator pitch + +This project takes on a machine learning model with the goal of predicting wether houses in Denver, Colorado, were built before or after 1980, with an accuracy rating of 90%. In the analysis, we focused on features like living area, number of bedrooms and bathrooms, and stories are significant points of focus between the change in house designs before and after 1980. I then used a couple of evaluation methods to validate the effectiveness of the Random Forest classifier used for this project! + +```{python} +#| label: project-data +#| code-summary: Read and format project data + +# Learn morea about Code Cells: https://quarto.org/docs/reference/cells/cells-jupyter.html + +# Include and execute your code here +df = pd.read_csv('/Users/maxsmith/Desktop/DS 250/week-8/dwellings_ml.csv') +``` + +__Highlight the Questions and Tasks__ + +## QUESTION|TASK 1 + +Create 2-3 charts that evaluate potential relationships between the home variables and before1980. Explain what you learn from the charts that could help a machine learning algorithm. + + +```{python} +#| label: Q1 +#| code-summary: Read and format data +# Include and execute your code here + +# df.drop('yrbuilt') +``` + +In this first chart we can see that before 1980 the living area is pretty dense at 2404 sq ft, while after 1980 there is more of a spread. Although the tail of the violin chart is highest before 1980, that is just because of that one point skewing the data. For the most part before 1980 is more dense and after 1980 is more spread, but they are both pretty similar. + +```{python} +#| label: Q1a-chart +#| code-summary: plot example +#| fig-cap: "Distribution of Living Area by Year Built Category" +#| fig-align: center +# Include and execute your code here +chart = px.violin(df, + x="before1980", + y="livearea", + color='before1980', + box=True +) + +chart.show() +``` + +In this graph we see that after 1980 has a much larger spread in netprice of homes than before 1980. Before, there were many houses around 600k, and after 1980 there are now a lot more houses above a million. + +```{python} +#| label: Q1b-chart +#| code-summary: plot example +#| fig-cap: "Comparison of Net Price for Houses Based on Year Built" +#| fig-align: center +# Include and execute your code here +chart = px.violin(df, + x="before1980", + y="netprice", + color='before1980' +) + +chart.show() +``` + +This graph shows us that there seems to be more homes in the data set before 1980 than after, but also that the majority of 2 bedroom homes are from before 1980. For both before and after most homes are between 1-4 rooms, primarily 2-3. + +```{python} +#| label: Q1c-chart +#| code-summary: plot example +#| fig-cap: "Number of Bedrooms Distribution Across Construction Eras" +#| fig-align: center +# Include and execute your code here + +chart = px.histogram(df, + x="numbdrm", + color="before1980", + barmode="group", + title="Distribution of Bedroom Count by Construction Era") + +chart.show() + +``` + + +## QUESTION|TASK 2 + +Build a classification model labeling houses as being built “before 1980” or “during or after 1980”. Your goal is to reach or exceed 90% accuracy. Explain your final model choice (algorithm, tuning parameters, etc) and describe what other models you tried. + +I was able to reach 90% with an occasional 89% through the random forrest classifier. I started with the GaussianNB classifier and I couldn't get better than a 76%. I had messed around with adding and dropping features to see which ones helped. Then with the random forest, I started at 82% and messing with the test size I got it up to 87%, and finally tweaked the n estimators to be 200 which brought the accuracy to 90%. + +```{python} +#| label: Q2 +#| code-summary: Read and format data +# Include and execute your code here + +# Select features that might influence the construction year of the house +features = df[['livearea', 'basement', 'stories', 'nocars', 'numbdrm', 'numbaths']] + +# Target variable +target = df['before1980'] + +# Split the dataset into training and testing sets +train_features, test_features, train_target, test_target = train_test_split(features, target, test_size=0.2) + +classifier = RandomForestClassifier(n_estimators=200) + +# Train the classifier +classifier.fit(train_features, train_target) + +# Make predictions on the test set +predictions = classifier.predict(test_features) + +# Calculate the accuracy +accuracy = accuracy_score(test_target, predictions) +print(f'Random Forest Accuracy: {accuracy:.5f}') +``` + + +## QUESTION|TASK 3 + +Justify your classification model by discussing the most important features selected by your model. This discussion should include a chart and a description of the features. + +As this graph clearly shows, the living area more than doubles the next (basement) importance by more than double. This shows us how important each of these features are for our model and testing. I found it interesting th number of cars was important at all, even more so, not being last. This shows us that the biggest difference from homes before and after 1980 is the size of the living area. +```{python} +#| label: Q3 +#| code-summary: Read and format data +# Include and execute your code here +feature_importances = pd.DataFrame(classifier.feature_importances_, + index=features.columns, + columns=['importance']).sort_values('importance', ascending=False) + +# Reset index to get feature names into a column +feature_importances.reset_index(inplace=True) +feature_importances.rename(columns={'index': 'feature'}, inplace=True) + +``` + + +```{python} +#| label: Q3-chart +#| code-summary: plot example +#| fig-cap: "My useless chart" +#| fig-align: center +# Include and execute your code here +chart = px.bar(feature_importances, + x='importance', + y='feature', + orientation='h', + title='Feature Importance for Predicting Construction Year', + labels={'feature': 'Feature', 'importance': 'Importance Score'}, + height=600, + color='importance', + color_continuous_scale=px.colors.sequential.Viridis) +# order it +chart.update_layout(yaxis={'categoryorder': 'total ascending'}) + +chart.show() +``` + +## QUESTION|TASK 4 + +Describe the quality of your classification model using 2-3 different evaluation metrics. You also need to explain how to interpret each of the evaluation metrics you use. + +The evaluation methods I chose are accuracy, confusion matrix, and precision. Accuracy is pretty straightforward, basically with an accuracy of .90, it means that 9/10 times our answer wil be right. The Confusion Matrix shows us exactly where our predictions land. It tells us the model correctly predicted "before 1980" for 1490 houses and "after 1980" for 2622 houses. It also shows where it got it wrong, with 231 mistakes for "before 1980" and 240 for "after 1980". Essentially, it breaks down the hits and misses, making it clear where the model excels or slips up. Prediction is the 'Ability of a model to identify only the relevant data points.' Our score for prediction was 92% which is very high!! + +```{python} +#| label: Q4 +#| code-summary: Read and format data +# Include and execute your code here + +# Accuracy +accuracy = accuracy_score(test_target, predictions) +print(f'Accuracy: {accuracy:.2f}') + +# Confusion Matrix +conf_matrix = confusion_matrix(test_target, predictions) +print(f'Confusion Matrix:\n{conf_matrix}') + +# Precision +precision = precision_score(test_target, predictions) +print(f'Precision: {precision:.2f}') + +``` + + diff --git a/docs/project_5.qmd b/docs/project_5.qmd new file mode 100644 index 0000000..0b5d7ca --- /dev/null +++ b/docs/project_5.qmd @@ -0,0 +1,332 @@ +--- +title: "Client Report - Project 5: The war with Star Wars" +subtitle: "Course DS 250" +author: "Max Smith" +format: + html: + self-contained: true + page-layout: full + title-block-banner: true + toc: true + toc-depth: 3 + toc-location: body + number-sections: false + html-math-method: katex + code-fold: true + code-summary: "Show the code" + code-overflow: wrap + code-copy: hover + code-tools: + source: false + toggle: true + caption: See code +execute: + warning: false + +--- + +```{python} +#| label: libraries +#| include: false +import pandas as pd +import numpy as np +import plotly.express as px +from sklearn.tree import DecisionTreeClassifier # Import Decision Tree Classifier +from sklearn import metrics #Import scikit-learn metrics module for accuracy calculation +from sklearn.model_selection import train_test_split +from sklearn.naive_bayes import GaussianNB +from sklearn.ensemble import RandomForestClassifier +from sklearn.metrics import accuracy_score, confusion_matrix, precision_score, recall_score, f1_score +from sklearn.linear_model import LogisticRegression + + +``` + + +## Elevator pitch + +In this analysis we are taking a look into survey data gathered on star wars from the public. A lot of analysis and data cleaning was done on this data to turn the survey data with long questions as headers, into a machine learning data frame. In this we take a look at how we made the data easier to read, a couple graphics from the data like which star wars movie was the most seen, and a machine learning system that acheives a 74% accuracy. + +```{python} +#| label: project-data +#| code-summary: Read and format project data + +# Learn morea about Code Cells: https://quarto.org/docs/reference/cells/cells-jupyter.html + +# Include and execute your code here +df = pd.read_csv('/Users/maxsmith/Desktop/DS 250/week-9/StarWars.csv', encoding='ISO-8859-1') +``` + +__Highlight the Questions and Tasks__ + +## QUESTION|TASK 1 + +Shorten the column names and clean them up for easier use with pandas. Provide a table or list that exemplifies how you fixed the names. + +Here I was able to change the super long header questions to more concise headers with no spaces but underscores. Here is a list of the new column names. + +```{python} +#| label: Q1 +#| code-summary: Read and format data +# Include and execute your code here + +df.columns = [ + 'respondent_id', + 'seen_any_star_wars_films', + 'star_wars_fan', + 'seen_episode_1_phantom_menace', + 'seen_episode_2_attack_of_clones', + 'seen_episode_3_revenge_of_sith', + 'seen_episode_4_new_hope', + 'seen_episode_5_empire_strikes_back', + 'seen_episode_6_return_of_jedi', + 'rank_episode_1_phantom_menace', + 'rank_episode_2_attack_of_clones', + 'rank_episode_3_revenge_of_sith', + 'rank_episode_4_new_hope', + 'rank_episode_5_empire_strikes_back', + 'rank_episode_6_return_of_jedi', + 'opinion_han_solo', + 'opinion_luke_skywalker', + 'opinion_princess_leia_organa', + 'opinion_anakin_skywalker', + 'opinion_obi_wan_kenobi', + 'opinion_emperor_palpatine', + 'opinion_darth_vader', + 'opinion_lando_calrissian', + 'opinion_boba_fett', + 'opinion_c3po', + 'opinion_r2d2', + 'opinion_jar_jar_binks', + 'opinion_padme_amidala', + 'opinion_yoda', + 'who_shot_first', + 'familiar_with_expanded_universe', + 'fan_of_expanded_universe', + 'fan_of_star_trek', + 'gender', + 'age', + 'household_income', + 'education', + 'location' +] + +df = df.drop(index=0) +df.reset_index(drop=True, inplace=True) + +df.columns + +``` + + +## QUESTION|TASK 2 + +Clean and format the data so that it can be used in a machine learning model. As you format the data, you should complete each item listed below. In your final report provide example(s) of the reformatted data with a short description of the changes made. +a. Filter the dataset to respondents that have seen at least one film. +b. Create a new column that converts the age ranges to a single number. Drop the age range categorical column. +c. Create a new column that converts the education groupings to a single number. Drop the school categorical column +d. Create a new column that converts the income ranges to a single number. Drop the income range categorical column. +e. Create your target (also known as “y” or “label”) column based on the new income range column. +f. One-hot encode all remaining categorical columns. + +In this task I was able to convert the values in different columns to make them useable in machine learning. For example, I made category values for range values like in age and income, so the maching can use a number value from 0-3 for example. Also I one-hot encoded the rest of the columns that werent a numeric range. + +```{python} +#| label: Q2 +#| code-summary: Read and format data +# Include and execute your code here + +# Part A +# df['seen_any_star_wars_films'].unique() +df_filtered = df[df['seen_any_star_wars_films'] == 'Yes'] + +# Part B +# df['age'].unique() +age_mapping = { + '18-29': 0, + '30-44': 1, + '45-60': 2, + '60+': 3 +} + +df_filtered['age_ml'] = df_filtered['age'].map(age_mapping) + +df_filtered.drop('age', axis=1, inplace=True) + +df_filtered + +# Part C +# df['education'].unique() +education_mapping = { + 'Less than high school degree': 0, + 'High school degree': 1, + 'Some college or Associate degree': 2, + 'Bachelor degree': 3, + 'Graduate degree': 4 +} + +df_filtered['education_ml'] = df_filtered['education'].map(education_mapping) + +df_filtered.drop('education', axis=1, inplace=True) + +# Part D +# df['household_income'].unique() +income_ordinal_mapping = { + '$0 - $24,999': 0, + '$25,000 - $49,999': 1, + '$50,000 - $99,999': 2, + '$100,000 - $149,999': 3, + '$150,000+': 4 +} + +df_filtered['income_ml'] = df_filtered['household_income'].map(income_ordinal_mapping) + +df_filtered.drop('household_income', axis=1, inplace=True) + +# Part E +y = (df_filtered['income_ml'] > 2).astype(int) + + +# Part F +df_features = df_filtered.drop(['income_ml'], axis=1) + +df_ml = pd.get_dummies(df_features, drop_first=True) + + +``` + +_include figures in chunks and discuss your findings in the figure._ + +## QUESTION|TASK 3 + +Validate that the data provided on GitHub lines up with the article by recreating 2 of the visuals from the article. + +I recreated the chart that compares the percentage of seen star wars movies to each other, and a graph that shows the movies ranks. While I wasn't able tp get my numbers exactly right, I did make the graphs very similar, and can see the results. +```{python} +#| label: Q3a +#| code-summary: Read and format data +# Include and execute your code here + +movies_columns = ['seen_episode_1_phantom_menace', 'seen_episode_2_attack_of_clones', +'seen_episode_3_revenge_of_sith', +'seen_episode_4_new_hope', +'seen_episode_5_empire_strikes_back', 'seen_episode_6_return_of_jedi'] + +movies_seen_percentages = df_filtered[movies_columns].notnull().mean() * 100 + +df_movies_seen = pd.DataFrame({ + 'Movie': ['Episode I The Phantom Menace', + 'Episode II Attack of the Clones', + 'Episode III Revenge of the Sith', + 'Episode IV A New Hope', + 'Episode V The Empire Strikes Back', + 'Episode VI Return of the Jedi'], + 'Percentage Seen': movies_seen_percentages.values.round(0) +}) + + +``` + + + +In this chart we can see that the fifth episode "The Empire Strikes Back" is the most watched movie with 81%, while the 3rd "Revenge of the Sith" is the least watched with 59%. + +```{python} +#| label: Q3a-chart +#| code-summary: plot example +#| fig-cap: "My useless chart" +#| fig-align: center +# Include and execute your code here + +fig = px.bar(df_movies_seen, y='Movie', x='Percentage Seen', + title="Which 'Star Wars' Movie Have You Seen?", + labels={'Percentage Seen': 'Percentage of Respondents (%)'}, + orientation='h', + text='Percentage Seen', + category_orders={'Movie': movies_columns}) + +fig.show() + +``` + +```{python} +#| label: Q3b +#| code-summary: Read and format data +# Include and execute your code here + +# List of columns to convert +rank_columns = [ + 'rank_episode_1_phantom_menace', 'rank_episode_2_attack_of_clones', + 'rank_episode_3_revenge_of_sith', 'rank_episode_4_new_hope', + 'rank_episode_5_empire_strikes_back', 'rank_episode_6_return_of_jedi' +] + +# Convert each column to numeric, using pd.to_numeric and .loc for safe operation +for col in rank_columns: + df_filtered.loc[:, col] = pd.to_numeric(df_filtered[col], errors='coerce') + +average_ranks = df_filtered[rank_columns].mean() + +df_movies_ranks = pd.DataFrame({ + 'Movie': [ + 'The Phantom Menace', 'Attack of the Clones', + 'Revenge of the Sith', 'A New Hope', + 'The Empire Strikes Back', 'Return of the Jedi' + ], + 'Average Rank': average_ranks.values +}) + + + +``` + +In this chart we see the different ranks, I couldn't figure out how to get them to show the same data, but we can see that the average rank for 3 of them were 3 and the other 3 had a rank of 4, and the lower the rank the better. +```{python} +#| label: Q3b-chart +#| code-summary: plot example +#| fig-cap: "My useless chart" +#| fig-align: center +# Include and execute your code here + +fig = px.bar(df_movies_ranks, x='Average Rank', y='Movie', orientation='h', + title="Star Wars Movies Ranked by Average Survey Rank", + labels={'Average Rank': 'Average Rank (Lower is Better)'}, + text='Average Rank') + +# Show the plot +fig.show() + + + +``` + + +## QUESTION|TASK 4 + +Build a machine learning model that predicts whether a person makes more than $50k. Describe your model and report the accuracy. + +In this model we started with a Gaussian model, and had an accuracy of 74.19%. We then tried a random forest classifier, and ended with the same 74.19% even after changing trees and n estimators. Obviously 74% isn't as great as 90% accuracy, but it is still a pretty good model, and not a bad accuracy at all. + +```{python} +#| label: Q4 +#| code-summary: Read and format data +# Include and execute your code here + +X_train, X_test, y_train, y_test = train_test_split(df_ml, y, test_size=0.2, random_state=42) + +X_train_dropped = X_train.dropna() +y_train_dropped = y_train.loc[X_train_dropped.index] + +X_test_dropped = X_test.dropna() +y_test_dropped = y_test.loc[X_test_dropped.index] + +random_forest_model = RandomForestClassifier(n_estimators=200, random_state=50) + +random_forest_model.fit(X_train_dropped, y_train_dropped) + +rf_predictions = random_forest_model.predict(X_test_dropped) + +rf_accuracy = accuracy_score(y_test_dropped, rf_predictions) +print(f"Random Forest Model Accuracy: {rf_accuracy * 100:.2f}%") + +``` \ No newline at end of file