dataset_thyroid_cancer <- read_csv("C:/Users/Local_123/OneDrive/Desktop/project _1 482/dataset thyroid cancer.csv")
## Rows: 212691 Columns: 17
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (11): Gender, Country, Ethnicity, Family_History, Radiation_Exposure, Io...
## dbl (6): Patient_ID, Age, TSH_Level, T3_Level, T4_Level, Nodule_Size
##
## ℹ 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.
View(dataset_thyroid_cancer)
there are 212691 rows and 17 columns in the dataset
data=dataset_thyroid_cancer
View(data)
str(data)
## spc_tbl_ [212,691 × 17] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ Patient_ID : num [1:212691] 1 2 3 4 5 6 7 8 9 10 ...
## $ Age : num [1:212691] 66 29 86 75 35 89 89 38 17 36 ...
## $ Gender : chr [1:212691] "Male" "Male" "Male" "Female" ...
## $ Country : chr [1:212691] "Russia" "Germany" "Nigeria" "India" ...
## $ Ethnicity : chr [1:212691] "Caucasian" "Hispanic" "Caucasian" "Asian" ...
## $ Family_History : chr [1:212691] "No" "No" "No" "No" ...
## $ Radiation_Exposure : chr [1:212691] "Yes" "Yes" "No" "No" ...
## $ Iodine_Deficiency : chr [1:212691] "No" "No" "No" "No" ...
## $ Smoking : chr [1:212691] "No" "No" "No" "No" ...
## $ Obesity : chr [1:212691] "No" "No" "No" "No" ...
## $ Diabetes : chr [1:212691] "No" "No" "No" "No" ...
## $ TSH_Level : num [1:212691] 9.37 1.83 6.26 4.1 9.1 4 4.7 5.54 2.3 1.34 ...
## $ T3_Level : num [1:212691] 1.67 1.73 2.59 2.62 2.11 0.98 0.62 3.49 2.6 0.56 ...
## $ T4_Level : num [1:212691] 6.16 10.54 10.57 11.04 10.71 ...
## $ Nodule_Size : num [1:212691] 1.08 4.05 4.61 2.46 2.11 0.02 0.01 4.3 0.81 1.44 ...
## $ Thyroid_Cancer_Risk: chr [1:212691] "Low" "Low" "Low" "Medium" ...
## $ Diagnosis : chr [1:212691] "Benign" "Benign" "Benign" "Benign" ...
## - attr(*, "spec")=
## .. cols(
## .. Patient_ID = col_double(),
## .. Age = col_double(),
## .. Gender = col_character(),
## .. Country = col_character(),
## .. Ethnicity = col_character(),
## .. Family_History = col_character(),
## .. Radiation_Exposure = col_character(),
## .. Iodine_Deficiency = col_character(),
## .. Smoking = col_character(),
## .. Obesity = col_character(),
## .. Diabetes = col_character(),
## .. TSH_Level = col_double(),
## .. T3_Level = col_double(),
## .. T4_Level = col_double(),
## .. Nodule_Size = col_double(),
## .. Thyroid_Cancer_Risk = col_character(),
## .. Diagnosis = col_character()
## .. )
## - attr(*, "problems")=<externalptr>
class(data)
## [1] "spec_tbl_df" "tbl_df" "tbl" "data.frame"
• The dataset consists of 17 variables, including numeric (num), character (chr), and categorical data. Below is an interpretation of each column:
• Numeric Variables (num): Age, TSH_Level, T3_Level, T4_Level, Nodule_Size.
• Categorical Variables (chr): Gender, Country, Ethnicity, Risk Factors (like Smoking, Obesity), and Diagnosis.
• Several risk factors (e.g., Radiation_Exposure, Iodine_Deficiency, Smoking) are stored as “Yes”/“No”.
sum(is.na(data))
## [1] 0
colSums(is.na(data))
## Patient_ID Age Gender Country
## 0 0 0 0
## Ethnicity Family_History Radiation_Exposure Iodine_Deficiency
## 0 0 0 0
## Smoking Obesity Diabetes TSH_Level
## 0 0 0 0
## T3_Level T4_Level Nodule_Size Thyroid_Cancer_Risk
## 0 0 0 0
## Diagnosis
## 0
• The result shows 0 missing values for every column in the dataset. • This indicates that there are no missing (NA) values in any column, meaning the dataset is complete and clean in terms of missing data.
summary(data)
## Patient_ID Age Gender Country
## Min. : 1 Min. :15.00 Length:212691 Length:212691
## 1st Qu.: 53174 1st Qu.:33.00 Class :character Class :character
## Median :106346 Median :52.00 Mode :character Mode :character
## Mean :106346 Mean :51.92
## 3rd Qu.:159519 3rd Qu.:71.00
## Max. :212691 Max. :89.00
## Ethnicity Family_History Radiation_Exposure Iodine_Deficiency
## Length:212691 Length:212691 Length:212691 Length:212691
## Class :character Class :character Class :character Class :character
## Mode :character Mode :character Mode :character Mode :character
##
##
##
## Smoking Obesity Diabetes TSH_Level
## Length:212691 Length:212691 Length:212691 Min. : 0.100
## Class :character Class :character Class :character 1st Qu.: 2.570
## Mode :character Mode :character Mode :character Median : 5.040
## Mean : 5.045
## 3rd Qu.: 7.520
## Max. :10.000
## T3_Level T4_Level Nodule_Size Thyroid_Cancer_Risk
## Min. :0.500 Min. : 4.500 Min. :0.000 Length:212691
## 1st Qu.:1.250 1st Qu.: 6.370 1st Qu.:1.250 Class :character
## Median :2.000 Median : 8.240 Median :2.510 Mode :character
## Mean :2.002 Mean : 8.246 Mean :2.503
## 3rd Qu.:2.750 3rd Qu.:10.120 3rd Qu.:3.760
## Max. :3.500 Max. :12.000 Max. :5.000
## Diagnosis
## Length:212691
## Class :character
## Mode :character
##
##
##
The dataset contains information for 212,691 patients.
Age ranges from 15 to 89 years, with an average age of 51.92 years.
Variables like Gender, Country, Ethnicity, Family History, Radiation Exposure, Iodine Deficiency, Smoking, Obesity, Diabetes, Thyroid Cancer Risk, and Diagnosis are stored as characters (text), meaning they contain categories rather than numerical values.
o The most common category (mode) for each of these is not displayed, but we can assume that some values occur more frequently.
Thyroid-Related Medical Indicators:
TSH Level (Thyroid-Stimulating Hormone):
Ranges from 0.1 to 10.0. The median value (middle value) is 5.04, which suggests that half of the patients have a TSH level below this and half above. The mean (average) is 5.045, which is very close to the median, indicating a relatively balanced distribution.
T3 Level (Triiodothyronine):
Ranges from 0.5 to 3.5. The median value is 2.002, and the mean is 2.002, suggesting a symmetrical distribution.
T4 Level (Thyroxine):
Ranges from 4.5 to 12.0. he median is 8.246, and the mean is also 8.246, again showing balance in distribution.
Nodule Size:
Ranges from 0.0 to 5.0. The median is 2.51, meaning half of the patients have nodules smaller than this, and half have larger.
nrow(filter(data, Age > 50))
## [1] 110269
nrow(filter(data, Age > 50 &Family_History =="Yes"))
## [1] 33220
nrow(filter(data, Age > 50 &Family_History =="No"))
## [1] 77049
nrow(filter(data, Age < 30 & Family_History == "Yes"))
## [1] 12644
nrow(filter(data, Age < 30 & Family_History == "No"))
## [1] 30013
• Thyroid issues increase with age → More cases are seen in patients above 50 than in younger ones.
• Family history plays a role, but not the biggest factor → More older patients (77,049) have no family history, meaning other risk factors contribute more.
• Younger patients mostly have no family history → But a significant portion (12,644) do, meaning genetic risks start early for some individuals.
table(data$Gender)
##
## Female Male
## 127527 85164
• The dataset has significantly more female patients (127,527) than males (85,164).
gender_age <- data %>%
group_by(Diagnosis, Gender) %>%
summarise(Average_Age = mean(Age, na.rm = TRUE)) %>%
arrange(desc(Average_Age))
## `summarise()` has grouped output by 'Diagnosis'. You can override using the
## `.groups` argument.
print("Average Age by Gender for Benign and Malignant Cases:")
## [1] "Average Age by Gender for Benign and Malignant Cases:"
print(gender_age)
## # A tibble: 4 × 3
## # Groups: Diagnosis [2]
## Diagnosis Gender Average_Age
## <chr> <chr> <dbl>
## 1 Malignant Male 52.0
## 2 Benign Female 51.9
## 3 Malignant Female 51.9
## 4 Benign Male 51.9
• Age Similarity: The average ages across all four groups (Benign Male, Benign Female, Malignant Male, Malignant Female) are remarkably similar, all falling around 51.9 to 52 years old.
country_cases <- data %>%
group_by(Diagnosis, Country) %>%
summarise(Count = n()) %>%
arrange(Diagnosis, desc(Count))
## `summarise()` has grouped output by 'Diagnosis'. You can override using the
## `.groups` argument.
print("Country with the Highest Cases for Each Diagnosis:")
## [1] "Country with the Highest Cases for Each Diagnosis:"
print(country_cases)
## # A tibble: 20 × 3
## # Groups: Diagnosis [2]
## Diagnosis Country Count
## <chr> <chr> <int>
## 1 Benign India 28520
## 2 Benign China 25280
## 3 Benign Nigeria 25206
## 4 Benign Brazil 16934
## 5 Benign Russia 16790
## 6 Benign Japan 13388
## 7 Benign South Korea 11882
## 8 Benign USA 8439
## 9 Benign UK 8417
## 10 Benign Germany 8340
## 11 Malignant India 13976
## 12 Malignant Nigeria 6712
## 13 Malignant China 6698
## 14 Malignant Russia 4507
## 15 Malignant Brazil 4479
## 16 Malignant Japan 3479
## 17 Malignant South Korea 3083
## 18 Malignant UK 2225
## 19 Malignant Germany 2217
## 20 Malignant USA 2119
• India Dominates: India stands out with the highest number of both benign and malignant thyroid cancer cases.
• High Benign Case Counts: The count of benign cases is generally higher than the count of malignant cases across all countries. This is consistent with the understanding that benign thyroid conditions are more common than malignant ones.
• Similar Patterns: The countries with high benign case counts also tend to have high malignant case counts. This suggests that factors influencing benign conditions might also contribute to malignant conditions in these regions.
factor_comparison <- data %>%
group_by(Diagnosis) %>%
summarise(
Avg_TSH = mean(TSH_Level, na.rm = TRUE),
Avg_T3 = mean(T3_Level, na.rm = TRUE),
Avg_T4 = mean(T4_Level, na.rm = TRUE),
Avg_Nodule_Size = mean(Nodule_Size, na.rm = TRUE)
)
print("Comparison of Factors (TSH, T3, T4, Nodule Size) for Benign vs Malignant:")
## [1] "Comparison of Factors (TSH, T3, T4, Nodule Size) for Benign vs Malignant:"
print(factor_comparison)
## # A tibble: 2 × 5
## Diagnosis Avg_TSH Avg_T3 Avg_T4 Avg_Nodule_Size
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 Benign 5.05 2.00 8.24 2.51
## 2 Malignant 5.03 2.00 8.25 2.50
o There is no significant difference in TSH levels,T4 levels ,Avg_nodule size between benign and malignant cases.
risk_factors <- data %>%
group_by(Diagnosis) %>%
summarise(
Radiation_Exposure = sum(Radiation_Exposure == "Yes") / n() * 100,
Iodine_Deficiency = sum(Iodine_Deficiency == "Yes") / n() * 100,
Smoking = sum(Smoking == "Yes") / n() * 100,
Obesity = sum(Obesity == "Yes") / n() * 100
)
print(risk_factors)
## # A tibble: 2 × 5
## Diagnosis Radiation_Exposure Iodine_Deficiency Smoking Obesity
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 Benign 13.2 22.6 19.9 30.1
## 2 Malignant 20.7 32.7 20.0 29.9
• Radiation Exposure is much higher in malignant cases (20.7% vs. 13.2%)
• Iodine Deficiency is significantly higher in malignant cases (32.7% vs. 22.6%)
• Smoking has no major difference (19.9% vs. 20.0%)
• Obesity is almost equal in both groups (30.1% vs. 29.9%)
data %>%
filter(Thyroid_Cancer_Risk == "High") %>%
group_by(Gender, Age) %>%
summarise(Count = n()) %>%
arrange(desc(Count))
## `summarise()` has grouped output by 'Gender'. You can override using the
## `.groups` argument.
## # A tibble: 150 × 3
## # Groups: Gender [2]
## Gender Age Count
## <chr> <dbl> <int>
## 1 Female 75 300
## 2 Female 50 290
## 3 Female 26 281
## 4 Female 42 280
## 5 Female 80 279
## 6 Female 36 278
## 7 Female 43 278
## 8 Female 40 274
## 9 Female 76 274
## 10 Female 33 273
## # ℹ 140 more rows
The highest number of high-risk cases is among females.
The top 10 age groups with the highest cases are all female.
The highest number of cases is seen at age 75 (300 cases).
Thyroid cancer risk is prevalent across multiple age groups in females.
The top affected ages include 75, 50, 26, 42, 80, 36, 43, 40, 76, and 33.
This suggests a widespread risk across both younger and older age groups in females.
radiation_by_country <- data %>%
filter(Radiation_Exposure == "Yes") %>%
group_by(Country) %>%
summarise(Count = n()) %>%
arrange(desc(Count))
print(radiation_by_country)
## # A tibble: 10 × 2
## Country Count
## <chr> <int>
## 1 India 6295
## 2 China 4924
## 3 Nigeria 4780
## 4 Brazil 3274
## 5 Russia 3167
## 6 Japan 2483
## 7 South Korea 2259
## 8 UK 1600
## 9 Germany 1539
## 10 USA 1539
• India has the highest number of radiation-exposed patients (6,295), followed by China (4,924) and Nigeria (4,780). • Countries like Brazil (3,274), Russia (3,167), and Japan (2,483) also have a significant number of cases. • Developed nations such as the UK (1,600), Germany (1,539), and the USA (1,539) also appear in the list, though with lower counts.
# Filter High-Risk patients
high_risk_patients <- data %>% filter(Thyroid_Cancer_Risk == "High")
# Select only risk factors
risk_factors <- high_risk_patients %>%
select(Smoking, Obesity, Radiation_Exposure, Iodine_Deficiency, Diabetes)
# Calculate % of "Yes" for each risk factor
risk_factor_summary <- sapply(risk_factors, function(x) mean(x == "Yes") * 100)
# Convert to dataframe and sort descending
risk_factor_rank <- data.frame(Risk_Factor = names(risk_factor_summary),
Percentage = risk_factor_summary) %>%
arrange(desc(Percentage))
print(risk_factor_rank)
## Risk_Factor Percentage
## Iodine_Deficiency Iodine_Deficiency 47.19619
## Radiation_Exposure Radiation_Exposure 30.93753
## Obesity Obesity 29.69313
## Diabetes Diabetes 20.07962
## Smoking Smoking 19.96364
Iodine_Deficiency, 47.19619: Iodine deficiency is the most common risk factor, present in approximately 47.2% of the high-risk patients.
Radiation_Exposure, 30.93753: Radiation exposure is the second most common risk factor, affecting about 30.9% of the high-risk patients.
data <- data %>%
mutate(Age_Bucket = case_when(
Age <= 30 ~ "Young",
Age <= 60 ~ "Middle",
TRUE ~ "Senior"
))
table(data$Age_Bucket, data$Diagnosis)
##
## Benign Malignant
## Middle 65464 19817
## Senior 62784 19084
## Young 34948 10594
Most cases (both benign and malignant) occur in the Middle and Senior groups compared to the Young.
Malignant cases are significant even in the Young group (10,594 cases), though fewer than Middle/Senior.
Benign cases are consistently higher than malignant across all age groups.
data <- data %>%
mutate(Risk_Score = (Smoking == "Yes") + (Obesity == "Yes") + (Radiation_Exposure == "Yes") +
(Iodine_Deficiency == "Yes") + (Diabetes == "Yes"))
# Check
head(data[, c("Smoking", "Obesity", "Radiation_Exposure", "Iodine_Deficiency", "Diabetes", "Risk_Score")])
## # A tibble: 6 × 6
## Smoking Obesity Radiation_Exposure Iodine_Deficiency Diabetes Risk_Score
## <chr> <chr> <chr> <chr> <chr> <int>
## 1 No No Yes No No 1
## 2 No No Yes No No 1
## 3 No No No No No 0
## 4 No No No No No 0
## 5 No No Yes No No 1
## 6 Yes Yes No No No 2
# Step 1: Summarize malignant and benign counts per Risk_Score
risk_analysis <- data %>%
group_by(Risk_Score) %>%
summarise(
Benign = sum(Diagnosis == "Benign"),
Malignant = sum(Diagnosis == "Malignant"),
Total = n()
) %>%
mutate(
Malignancy_Rate = Malignant / Total
)
# Step 2: View the summarized table
print(risk_analysis)
## # A tibble: 6 × 5
## Risk_Score Benign Malignant Total Malignancy_Rate
## <int> <int> <int> <int> <dbl>
## 1 0 49093 11636 60729 0.192
## 2 1 67414 20192 87606 0.230
## 3 2 35982 12936 48918 0.264
## 4 3 9457 4048 13505 0.300
## 5 4 1186 648 1834 0.353
## 6 5 64 35 99 0.354
# Step 3: Plot Risk_Score vs Malignancy Rate
ggplot(risk_analysis, aes(x = Risk_Score, y = Malignancy_Rate)) +
geom_line(group = 1, color = "blue", size = 1) +
geom_point(color = "red", size = 3) +
labs(
title = "Malignancy Rate vs Lifestyle Risk Score",
x = "Risk Score",
y = "Malignancy Rate"
) +
theme_minimal()
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
Positive Trend: As Risk Score increases, the Malignancy
Rate also increases.
Patients with 0 risk factors have a malignancy rate around 19%.
Patients with 5 risk factors have a malignancy rate around 36%.
Sharp Rise after Score 3:
From Risk Score 3 to 5, the malignancy rate jumps sharply.
This suggests that when multiple risk factors are present, the cancer risk becomes much higher.
Plateau at High Risk Score:
From Risk Score 4 to 5, the line flattens, meaning malignancy risk stops increasing much after a very high risk score.
It might be because very few people have all 5 risk factors, so sample size becomes small.
high_risk_count <- sum(data$Thyroid_Cancer_Risk == "High", na.rm = TRUE)
total_patients <- nrow(data)
high_risk_percentage <- (high_risk_count / total_patients) * 100
print(paste("Percentage of High-Risk Individuals:", round(high_risk_percentage, 2), "%"))
## [1] "Percentage of High-Risk Individuals: 15 %"
• A 15% high-risk rate indicates a significant minority of the population is at serious risk and may require urgent diagnosis, monitoring, or intervention.
# TSH_Level
ggplot(data, aes(x = TSH_Level)) +
geom_histogram(binwidth = 0.5, fill = "skyblue", color = "black") +
labs(title = "Distribution of TSH Levels", x = "TSH Level", y = "Count")
# T3_Level
ggplot(data, aes(x = T3_Level)) +
geom_histogram(binwidth = 0.1, fill = "lightgreen", color = "black") +
labs(title = "Distribution of T3 Levels", x = "T3 Level", y = "Count")
# T4_Level
ggplot(data, aes(x = T4_Level)) +
geom_histogram(binwidth = 0.5, fill = "orange", color = "black") +
labs(title = "Distribution of T4 Levels", x = "T4 Level", y = "Count")
he histogram shows a relatively uniform distribution of TSH levels
across the majority of the range, from approximately 0.5 to
9.5.
ggplot(data, aes(x = Gender, fill = Diagnosis)) +
geom_bar(position = "dodge") +
labs(title = "Gender vs Diagnosis Distribution", x = "Gender", y = "Count")
Females have a much higher number of thyroid cancer cases overall (Benign + Malignant) compared to males.
Among both genders, Benign cases are more common than Malignant cases.
The difference between Benign and Malignant cases is bigger in females than in males.
Males have lower total numbers, but relatively a bit higher proportion of malignancy compared to females.
ggplot(data, aes(x = Diagnosis, y = Nodule_Size, fill = Diagnosis)) +
geom_boxplot() +
labs(title = "Nodule Size in Benign vs Malignant Cases", x = "Diagnosis", y = "Nodule Size")
The median (thick line inside the box) for both is almost the same —
around 2.5.
Nodule Size alone may not be a strong differentiator between Benign and Malignant nodules in this dataset.
library(corrplot)
## Warning: package 'corrplot' was built under R version 4.4.3
## corrplot 0.95 loaded
numeric_data <- data[, c("Age", "TSH_Level", "T3_Level", "T4_Level", "Nodule_Size")]
cor_matrix <- cor(numeric_data, use = "complete.obs")
corrplot(cor_matrix, method = "number", type = "lower")
T3_Level and T4_Level have strong positive correlation
(They move together: when T3 is high, T4 is high. Medically correct.)
all other pairs (like Age, TSH, Nodule Size) show:
–Very weak correlation (r very close to 0).
–No strong linear relationship between them.
model1 <- lm(TSH_Level ~ Age, data = data)
summary(model1)
##
## Call:
## lm(formula = TSH_Level ~ Age, data = data)
##
## Residuals:
## Min 1Q Median 3Q Max
## -4.9496 -2.4775 -0.0041 2.4794 4.9594
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 5.0514490 0.0161252 313.265 <2e-16 ***
## Age -0.0001222 0.0002867 -0.426 0.67
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 2.86 on 212689 degrees of freedom
## Multiple R-squared: 8.549e-07, Adjusted R-squared: -3.847e-06
## F-statistic: 0.1818 on 1 and 212689 DF, p-value: 0.6698
plot(data$Age, data$TSH_Level, pch=20, main="TSH vs Age")
abline(model1, col="red")
The scatter plot shows that the TSH Level values are very densely
packed vertically — almost forming vertical lines at each age
value.
The red regression line is almost flat, indicating that TSH Level doesn’t change much with Age.
No strong visible trend — TSH Levels seem almost randomly distributed across different ages.
model2 <- lm(Nodule_Size ~ Age + TSH_Level + T3_Level + T4_Level, data = data)
summary(model2)
##
## Call:
## lm(formula = Nodule_Size ~ Age + TSH_Level + T3_Level + T4_Level,
## data = data)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2.51396 -1.25221 0.00957 1.25170 2.50726
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 2.524e+00 1.712e-02 147.417 <2e-16 ***
## Age -9.981e-05 1.448e-04 -0.689 0.491
## TSH_Level 2.088e-04 1.095e-03 0.191 0.849
## T3_Level -3.015e-03 3.616e-03 -0.834 0.404
## T4_Level -1.248e-03 1.447e-03 -0.863 0.388
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 1.445 on 212686 degrees of freedom
## Multiple R-squared: 9.128e-06, Adjusted R-squared: -9.679e-06
## F-statistic: 0.4853 on 4 and 212686 DF, p-value: 0.7465
The predictors (Age, TSH, T3, and T4 levels) do not have a significant relationship with Nodule Size in this dataset.
top_countries <- data %>%
filter(Diagnosis == "Malignant") %>%
group_by(Country) %>%
summarise(Count = n()) %>%
arrange(desc(Count)) %>%
head(5)
ggplot(top_countries, aes(x = reorder(Country, -Count), y = Count, fill = Country)) +
geom_bar(stat = "identity") +
labs(title = "Top 5 Countries with Malignant Cases", x = "Country", y = "Cases")
The bar chart shows that India reports the highest number of
malignant thyroid cancer cases among the top five countries.
Nigeria and China follow, each having a comparable number of cases,
while Russia and Brazil have lower but still notable malignant case
counts.
anova_result <- aov(Nodule_Size ~ Thyroid_Cancer_Risk, data = data)
summary(anova_result)
## Df Sum Sq Mean Sq F value Pr(>F)
## Thyroid_Cancer_Risk 2 0 0.1713 0.082 0.921
## Residuals 212688 443875 2.0870
the p-value is 0.921, which is much greater than 0.05. Therefore, you fail to reject the null hypothesis. This means there is no statistically significant difference in Nodule Size among patients classified as Low, Medium, and High Risk.
ggplot(data, aes(x = Gender, y = Age, fill = Gender)) +
geom_boxplot() +
labs(title = "Age Distribution by Gender", x = "Gender", y = "Age")
The median age (thick black line inside each box) is almost
identical for both genders — slightly above 50 years.
The interquartile range (IQR) (the range of the box from Q1 to Q3) is quite similar for both males and females.
The spread (range from minimum to maximum age) also appears similar between males and females.
No extreme outliers are visible.
There is no major difference in the age distribution between male and female patients in this thyroid cancer dataset.
Both genders have a fairly similar age range and central tendency.
# Step 1: Create Age Groups (binning ages)
data <- data %>%
mutate(Age_Group = case_when(
Age <= 30 ~ "15-30",
Age <= 50 ~ "31-50",
Age <= 70 ~ "51-70",
TRUE ~ "71+"
))
# Step 2: Filter only High-Risk patients and group by Age Group
high_risk_grouped <- data %>%
filter(Thyroid_Cancer_Risk == "High") %>%
group_by(Age_Group) %>%
summarise(High_Risk_Count = n()) %>%
arrange(Age_Group) # Sort Age Groups properly
# Step 3: Plot Grouped Bar Chart
ggplot(high_risk_grouped, aes(x = Age_Group, y = High_Risk_Count, fill = Age_Group)) +
geom_bar(stat = "identity", width = 0.7) +
labs(title = "High-Risk Thyroid Cancer Cases Across Age Groups",
x = "Age Group",
y = "Number of High-Risk Cases") +
theme_minimal() +
theme(legend.position = "none") +
geom_text(aes(label = High_Risk_Count), vjust = -0.5) # Add count labels on bars
The grouped bar chart indicates that the maximum number of high-risk
thyroid cancer cases is observed in the 31–50 year age group, followed
closely by the 51–70 and 71+ age groups. Young adults aged 15–30 years
show relatively fewer high-risk cases. These results suggest that
thyroid cancer risk intensifies with age, particularly affecting
middle-aged and elderly individuals. However, the presence of a notable
number of high-risk cases even among young adults highlights the need
for early screening and preventive measures across all age
groups.
risk_counts <- table(data$Thyroid_Cancer_Risk)
pie(risk_counts, main = "Thyroid Cancer Risk Distribution", col = rainbow(length(risk_counts)))
The pie chart shows that a majority of the patients in the dataset
are categorized as Low Risk for thyroid cancer. Medium Risk patients
make up a moderate proportion, while High Risk patients constitute the
smallest group. This suggests that although most individuals are at a
lower risk, there remains a significant minority requiring close medical
monitoring and intervention.
ggplot(data, aes(x = Iodine_Deficiency, fill = Diagnosis)) +
geom_bar(position = "fill") +
labs(
title = "Proportion of Malignant vs Benign by Iodine Deficiency",
x = "Iodine Deficiency",
y = "Proportion"
) +
scale_y_continuous(labels = scales::percent) +
theme_minimal()
Iodine deficiency is associated with a higher risk of having
malignant thyroid cancer. Patients who have iodine deficiency
show a higher proportion of malignancy compared to patients who
don’t.
# Convert Diagnosis to binary (1=Malignant, 0=Benign)
data$Diagnosis_binary <- ifelse(data$Diagnosis == "Malignant", 1, 0)
# Fit logistic regression model
model_iodine <- glm(Diagnosis_binary ~ Iodine_Deficiency, data = data, family = "binomial")
# Model Summary
summary(model_iodine)
##
## Call:
## glm(formula = Diagnosis_binary ~ Iodine_Deficiency, family = "binomial",
## data = data)
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -1.333415 0.006159 -216.5 <2e-16 ***
## Iodine_DeficiencyYes 0.511372 0.011263 45.4 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 230782 on 212690 degrees of freedom
## Residual deviance: 228779 on 212689 degrees of freedom
## AIC: 228783
##
## Number of Fisher Scoring iterations: 4
“Patients who have Iodine Deficiency are 1.67 times more likely to have Malignant thyroid cancer compared to those without iodine deficiency, and the relationship is highly statistically significant (p < 0.001).”
From the proportion plot, it is observed that patients with iodine deficiency have a significantly higher proportion of malignant thyroid cancer compared to patients without iodine deficiency. In contrast, patients without iodine deficiency have a majority of benign cases. This visual finding aligns with the logistic regression output, confirming that iodine deficiency is an important risk factor for thyroid malignancy.
# Select High-Risk and Low-Risk individuals
high_risk <- data %>% filter(Thyroid_Cancer_Risk == "High")
low_risk <- data %>% filter(Thyroid_Cancer_Risk == "Low")
# Calculate percentage of each factor in High Risk
high_risk_factors <- colMeans(high_risk[, c("Smoking", "Obesity", "Radiation_Exposure", "Diabetes", "Iodine_Deficiency")] == "Yes") * 100
# Calculate percentage of each factor in Low Risk
low_risk_factors <- colMeans(low_risk[, c("Smoking", "Obesity", "Radiation_Exposure", "Diabetes", "Iodine_Deficiency")] == "Yes") * 100
# Combine into one dataframe
risk_compare <- data.frame(
Factor = names(high_risk_factors),
High_Risk_Percent = high_risk_factors,
Low_Risk_Percent = low_risk_factors
)
print(risk_compare)
## Factor High_Risk_Percent Low_Risk_Percent
## Smoking Smoking 19.96364 20.04834
## Obesity Obesity 29.69313 30.09743
## Radiation_Exposure Radiation_Exposure 30.93753 12.19415
## Diabetes Diabetes 20.07962 20.10001
## Iodine_Deficiency Iodine_Deficiency 47.19619 20.99679
library(tidyr)
# Pivot data for ggplot
risk_compare_melt <- pivot_longer(risk_compare,
cols = -Factor,
names_to = "variable",
values_to = "value")
# Plot
ggplot(risk_compare_melt, aes(x = Factor, y = value, fill = variable)) +
geom_bar(stat = "identity", position = "dodge") +
labs(title = "Comparison of Risk Factors in High vs Low Risk Individuals",
x = "Risk Factors", y = "Percentage (%)") +
theme_minimal()
Iodine Deficiency and Radiation Exposure are key distinguishing risk factors between high-risk and low-risk individuals.
Obesity, Diabetes, and Smoking do not show significant differences between the two groups in this data.