library(tidyverse)# Read dataadult <-read_csv("adult.csv", na =c("", "NA", "?"))
Rows: 32561 Columns: 15
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (9): workclass, education, marital.status, occupation, relationship, rac...
dbl (6): age, fnlwgt, education.num, capital.gain, capital.loss, hours.per.week
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
df_workclass_grouped <- adult %>%mutate(# Group workclass into 5 presentation-ready categoriesworkclass_clean =case_when( workclass =="Private"~"Private Sector", workclass %in%c("Local-gov", "State-gov", "Federal-gov") ~"Government", workclass %in%c("Self-emp-not-inc", "Self-emp-inc") ~"Self-Employed", workclass %in%c("Without-pay", "Never-worked") ~"Other / Unemployed",is.na(workclass) | workclass =="?"~"Unknown",TRUE~ workclass ),# Sort categories by frequencyworkclass_clean =fct_infreq(workclass_clean) )# Plot grouped workclass vs income levelggplot(df_workclass_grouped, aes(x = workclass_clean, fill = income)) +geom_bar(position ="dodge") +scale_fill_manual(values =c("<=50K"="#56B4E9", ">50K"="#D55E00")) +labs(title ="Income Distribution by Work Class",x ="Work Class",y ="Count",fill ="Income Group" ) +theme_classic() +theme(axis.text.x =element_text(angle =45, hjust =1))
library(tidyverse)# 1. Load data (treating "?" as missing NA values)adult <-read_csv("adult.csv", na =c("", "NA", "?"))
Rows: 32561 Columns: 15
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (9): workclass, education, marital.status, occupation, relationship, rac...
dbl (6): age, fnlwgt, education.num, capital.gain, capital.loss, hours.per.week
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
df_marital.status_grouped <- adult %>%mutate(# Group marital.status into 4 presentation-ready categories marital.status_clean =case_when( marital.status %in%c("Married-civ-spouse", "Married-spouse-absent", "Married-AF-spouse") ~"Married", marital.status %in%c("Divorced", "Separated") ~"Divorced", marital.status =="Widowed"~"Spouse Dead", marital.status =="Never-married"~"Single",TRUE~ marital.status ),# Sort categories by frequency marital.status_clean =fct_infreq(marital.status_clean) )# 2. Bar Graphggplot(df_marital.status_grouped, aes(x = marital.status_clean, fill = income)) +geom_bar(position ="dodge") +scale_fill_manual(values =c("<=50k"="#56B4E9", ">50K"="#D55E00")) +labs(title ="Income by Marital Status",x ="Status", y="Count" ) +theme_classic() +theme(axis.text.x =element_text(angle =45, hjust =1))
library(tidyverse)# 1. Read datasetadult <-read_csv("adult.csv", na =c("", "NA", "?"))
Rows: 32561 Columns: 15
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (9): workclass, education, marital.status, occupation, relationship, rac...
dbl (6): age, fnlwgt, education.num, capital.gain, capital.loss, hours.per.week
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# 2. Group occupations into 6 major industry sectorsdf_occ_grouped <- adult %>%mutate(occupation_sector =case_when( occupation %in%c("Prof-specialty", "Exec-managerial", "Tech-support") ~"Manage. & Professional", occupation %in%c("Adm-clerical", "Sales") ~"Sales & Office", occupation %in%c("Craft-repair", "Machine-op-inspct", "Transport-moving", "Handlers-cleaners") ~"Blue Collar & Trades", occupation %in%c("Other-service", "Protective-serv", "Priv-house-serv") ~"Services & Security", occupation =="Farming-fishing"~"Farming & Agriculture", occupation =="Armed-Forces"~"Military",is.na(occupation) | occupation =="?"~"Unknown",TRUE~ occupation ),# Sort bars by frequencyoccupation_sector =fct_infreq(occupation_sector) )# 3. Proportional Stacked Bar Graph (Shows % of high earners in each sector)ggplot(df_occ_grouped, aes(x = occupation_sector, fill = income)) +geom_bar(position ="fill") +scale_y_continuous(labels = scales::percent) +scale_fill_manual(values =c("<=50K"="#56B4E9", ">50K"="#D55E00")) +labs(title ="High Earners (>50K) Across Occupational Sectors",x ="Occupational Sector",y ="Percentage",fill ="Income Group" ) +theme_minimal() +theme(axis.text.x =element_text(angle =30, hjust =1))
Rows: 32561 Columns: 15
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (9): workclass, education, marital.status, occupation, relationship, rac...
dbl (6): age, fnlwgt, education.num, capital.gain, capital.loss, hours.per.week
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# 2. Relabel hyphenated values and sort by frequencydf_rel_sorted <- adult %>%mutate(relationship_clean =fct_recode( relationship,"Not in Family"="Not-in-family","Own Child"="Own-child","Other Relative"="Other-relative" ),# Order levels by size (most frequent to least frequent)relationship_clean =fct_infreq(relationship_clean) )# 3. Horizontal Bar Graphggplot(df_rel_sorted, aes(x =fct_rev(relationship_clean), fill = income)) +geom_bar(position ="dodge") +scale_fill_manual(values =c("<=50K"="#56B4E9", ">50K"="#D55E00")) +labs(title ="Household Relationship vs Income",x ="Relationship",y ="Count",fill ="Income Group" ) +theme_classic()
Rows: 32561 Columns: 15
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (9): workclass, education, marital.status, occupation, relationship, rac...
dbl (6): age, fnlwgt, education.num, capital.gain, capital.loss, hours.per.week
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Rows: 32561 Columns: 15
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (9): workclass, education, marital.status, occupation, relationship, rac...
dbl (6): age, fnlwgt, education.num, capital.gain, capital.loss, hours.per.week
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# 2. Clean/Factor the sex variabledf_sex <- adult %>%mutate(sex =factor(sex, levels =c("Male", "Female")) )# 3. Side-by-Side Bar Graphggplot(df_sex, aes(x = sex, fill = income)) +geom_bar(position ="dodge") +scale_fill_manual(values =c("<=50K"="#56B4E9", ">50K"="#D55E00")) +labs(title ="Income Level Distribution by Sex",x ="Sex",y ="Count",fill ="Income Group" ) +theme_classic()
# Map with United States separateddf_continent_split <- adult %>%mutate(continent =case_when( native.country =="United-States"~"United States", native.country %in%c("Canada", "Mexico") ~"Rest of North America", native.country %in%c("Puerto-Rico", "El-Salvador", "Cuba", "Jamaica", "Dominican-Republic", "Guatemala", "Haiti", "Nicaragua", "Trinadad&Tobago", "Honduras", "Columbia", "Ecuador", "Peru", "Outlying-US(Guam-USVI-etc)") ~"Central / South America & Caribbean", native.country %in%c("Germany", "England", "Italy", "Poland", "Portugal", "Greece", "Yugoslavia", "Ireland", "Hungary", "Scotland", "Holand-Netherlands") ~"Europe", native.country %in%c("Philippines", "India", "China", "Japan", "Vietnam", "Taiwan", "Iran", "Asian-Pac-Islander", "Thailand", "Cambodia", "Laos", "Hong") ~"Asia",is.na(native.country) ~"Unknown",TRUE~"Other" ),continent =fct_infreq(continent) )# Plot as horizontal bar countsggplot(df_continent_split, aes(y =fct_rev(continent), fill = income)) +geom_bar(position ="dodge") +scale_fill_manual(values =c("<=50K"="#56B4E9", ">50K"="#D55E00")) +labs(title ="Sample Count by Geographic Region of Origin",x ="Count",y ="Region",fill ="Income Group" ) +theme_minimal()
Rows: 32561 Columns: 15
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (9): workclass, education, marital.status, occupation, relationship, rac...
dbl (6): age, fnlwgt, education.num, capital.gain, capital.loss, hours.per.week
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# 2. Bin continuous age into decadesdf_age_decades <- adult %>%mutate(age_decade =cut( age,breaks =c(10, 20, 30, 40, 50, 60, 70, Inf),labels =c("Teens (17-19)", "20s", "30s", "40s", "50s", "60s", "70s+"),right =FALSE# Includes lower bound, e.g., 20 to 29 is "20s" ) )# 3. Option A: Proportional Stacked Bar Graph (100% Filled - Recommended)# Shows the percentage of high earners (>50K) in each decadeggplot(df_age_decades, aes(x = age_decade, fill = income)) +geom_bar(position ="fill") +scale_y_continuous(labels = scales::percent) +scale_fill_manual(values =c("<=50K"="#56B4E9", ">50K"="#D55E00")) +labs(title ="Proportions of Income Levels across Age Decades",x ="Age Decade",y ="Percentage",fill ="Income Group" ) +theme_minimal()
Rows: 32561 Columns: 15
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (9): workclass, education, marital.status, occupation, relationship, rac...
dbl (6): age, fnlwgt, education.num, capital.gain, capital.loss, hours.per.week
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# 2. Bin fnlwgt into population representation brackets (in groups of 100,000)df_fnlwgt_binned <- adult %>%mutate(weight_group =cut( fnlwgt,breaks =c(0, 100000, 200000, 300000, 400000, 500000, Inf),labels =c("<100k", "100k–200k", "200k–300k", "300k–400k", "400k–500k", "500k+"),right =FALSE ) )# 3. Bar Graph showing distribution of survey weightsggplot(df_fnlwgt_binned, aes(x = weight_group, fill = income)) +geom_bar(position ="dodge") +scale_fill_manual(values =c("<=50K"="#56B4E9", ">50K"="#D55E00")) +labs(title ="Distribution of Census Sample Weights (fnlwgt)",x ="Population Weight Group (Represented Individuals)",y ="Survey Row Count",fill ="Income Group" ) +theme_minimal()
Rows: 32561 Columns: 15
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (9): workclass, education, marital.status, occupation, relationship, rac...
dbl (6): age, fnlwgt, education.num, capital.gain, capital.loss, hours.per.week
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# 2. Bin capital gains into intuitive tiersdf_cap_gain_tiered <- adult %>%mutate(cap_gain_group =case_when( capital.gain ==0~"None ($0)", capital.gain >0& capital.gain <5000~"Low ($1–$4,999)", capital.gain >=5000& capital.gain <15000~"Medium ($5,000–$14,999)", capital.gain >=15000& capital.gain <99999~"High ($15,000–$99,998)", capital.gain ==99999~"Maximum ($99,999)",TRUE~"Other" ),# Set explicit ordering for the plotcap_gain_group =factor( cap_gain_group,levels =c("None ($0)", "Low ($1–$4,999)", "Medium ($5,000–$14,999)", "High ($15,000–$99,998)", "Maximum ($99,999)") ) )# 3. Bar Graphggplot(df_cap_gain_tiered, aes(x = cap_gain_group, fill = income)) +geom_bar(position ="dodge") +scale_fill_manual(values =c("<=50K"="#56B4E9", ">50K"="#D55E00")) +labs(title ="Income Level across Capital Gain Brackets",x ="Capital Gain Tier",y ="Count",fill ="Income Group" ) +theme_minimal() +theme(axis.text.x =element_text(angle =20, hjust =1))
Rows: 32561 Columns: 15
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (9): workclass, education, marital.status, occupation, relationship, rac...
dbl (6): age, fnlwgt, education.num, capital.gain, capital.loss, hours.per.week
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# 2. Bin capital loss into structured tiersdf_cap_loss_tiered <- adult %>%mutate(cap_loss_group =case_when( capital.loss ==0~"None ($0)", capital.loss >0& capital.loss <1600~"Low ($1–$1,599)", capital.loss >=1600& capital.loss <=2000~"Medium ($1,600–$2,000)", capital.loss >2000~"High ($2,001+)",TRUE~"Other" ),# Set explicit factor orderingcap_loss_group =factor( cap_loss_group,levels =c("None ($0)", "Low ($1–$1,599)", "Medium ($1,600–$2,000)", "High ($2,001+)") ) )# 3. Bar Graphggplot(df_cap_loss_tiered, aes(x = cap_loss_group, fill = income)) +geom_bar(position ="dodge") +scale_fill_manual(values =c("<=50K"="#56B4E9", ">50K"="#D55E00")) +labs(title ="Income Distribution across Capital Loss Tiers",x ="Capital Loss Bracket",y ="Count",fill ="Income Group" ) +theme_minimal() +theme(axis.text.x =element_text(angle =15, hjust =1))
Rows: 32561 Columns: 15
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (9): workclass, education, marital.status, occupation, relationship, rac...
dbl (6): age, fnlwgt, education.num, capital.gain, capital.loss, hours.per.week
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# 2. Bin hours.per.week into labor categoriesdf_hours_grouped <- adult %>%mutate(work_schedule =case_when( hours.per.week <35~"Part-Time (<35 hrs)", hours.per.week >=35& hours.per.week <=40~"Full-Time Standard (35–40 hrs)", hours.per.week >40& hours.per.week <=50~"Overtime (41–50 hrs)", hours.per.week >50~"Extended Overtime (50+ hrs)",TRUE~"Other" ),# Set explicit factor level orderwork_schedule =factor( work_schedule,levels =c("Part-Time (<35 hrs)", "Full-Time Standard (35–40 hrs)", "Overtime (41–50 hrs)", "Extended Overtime (50+ hrs)") ) )# 3. 100% Proportional Stacked Bar Graphggplot(df_hours_grouped, aes(x = work_schedule, fill = income)) +geom_bar(position ="fill") +scale_y_continuous(labels = scales::percent) +scale_fill_manual(values =c("<=50K"="#56B4E9", ">50K"="#D55E00")) +labs(title ="Proportion of High Earners (>50K) by Work Schedule",x ="Work Schedule Category",y ="Percentage",fill ="Income Group" ) +theme_minimal() +theme(axis.text.x =element_text(angle =15, hjust =1))