library(tidyverse)
── Attaching core tidyverse packages ────────────────────────────────────────────────────────────────────────────────── tidyverse 2.0.0 ──
✔ dplyr 1.1.4 ✔ readr 2.1.5
✔ forcats 1.0.0 ✔ stringr 1.5.1
✔ ggplot2 3.5.1 ✔ tibble 3.2.1
✔ lubridate 1.9.4 ✔ tidyr 1.3.1
✔ purrr 1.0.4 ── Conflicts ──────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
ℹ Use the ]8;;http://conflicted.r-lib.org/conflicted package]8;; to force all conflicts to become errors
library(ggplot2)
df <- read_csv("social_media_vs_productivity.csv")
Rows: 30000 Columns: 19── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (3): gender, job_type, social_platform_preference
dbl (14): age, daily_social_media_time, number_of_notifications, work_hours_per_day, perceived_productivity_score, actual_productivity...
lgl (2): uses_focus_apps, has_digital_wellbeing_enabled
ℹ 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.
head(df)
summary(df)
age gender job_type daily_social_media_time social_platform_preference number_of_notifications
Min. :18.00 Length:30000 Length:30000 Min. : 0.000 Length:30000 Min. :30.00
1st Qu.:30.00 Class :character Class :character 1st Qu.: 1.640 Class :character 1st Qu.:55.00
Median :41.00 Mode :character Mode :character Median : 3.026 Mode :character Median :60.00
Mean :41.49 Mean : 3.113 Mean :59.96
3rd Qu.:53.00 3rd Qu.: 4.369 3rd Qu.:65.00
Max. :65.00 Max. :17.973 Max. :90.00
NA's :2765
work_hours_per_day perceived_productivity_score actual_productivity_score stress_level sleep_hours screen_time_before_sleep
Min. : 0.000 Min. :2.000 Min. :0.2968 Min. : 1.000 Min. : 3.000 Min. :0.0000
1st Qu.: 5.644 1st Qu.:3.758 1st Qu.:3.3733 1st Qu.: 3.000 1st Qu.: 5.494 1st Qu.:0.5285
Median : 6.991 Median :5.525 Median :4.9517 Median : 6.000 Median : 6.498 Median :1.0062
Mean : 6.991 Mean :5.511 Mean :4.9518 Mean : 5.514 Mean : 6.500 Mean :1.0256
3rd Qu.: 8.355 3rd Qu.:7.266 3rd Qu.:6.5263 3rd Qu.: 8.000 3rd Qu.: 7.504 3rd Qu.:1.4772
Max. :12.000 Max. :8.999 Max. :9.8463 Max. :10.000 Max. :10.000 Max. :3.0000
NA's :1614 NA's :2365 NA's :1904 NA's :2598 NA's :2211
breaks_during_work uses_focus_apps has_digital_wellbeing_enabled coffee_consumption_per_day days_feeling_burnout_per_month
Min. : 0.000 Mode :logical Mode :logical Min. : 0.000 Min. : 0.00
1st Qu.: 2.000 FALSE:20979 FALSE:22602 1st Qu.: 1.000 1st Qu.: 8.00
Median : 5.000 TRUE :9021 TRUE :7398 Median : 2.000 Median :16.00
Mean : 4.992 Mean : 1.999 Mean :15.56
3rd Qu.: 8.000 3rd Qu.: 3.000 3rd Qu.:24.00
Max. :10.000 Max. :10.000 Max. :31.00
weekly_offline_hours job_satisfaction_score
Min. : 0.000 Min. : 0.000
1st Qu.: 4.542 1st Qu.: 3.364
Median :10.014 Median : 4.951
Mean :10.361 Mean : 4.965
3rd Qu.:15.301 3rd Qu.: 6.581
Max. :40.965 Max. :10.000
NA's :2730
str(df)
spc_tbl_ [30,000 × 19] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
$ age : num [1:30000] 56 46 32 60 25 38 56 36 40 28 ...
$ gender : chr [1:30000] "Male" "Male" "Male" "Female" ...
$ job_type : chr [1:30000] "Unemployed" "Health" "Finance" "Unemployed" ...
$ daily_social_media_time : num [1:30000] 4.18 3.25 NA NA NA ...
$ social_platform_preference : chr [1:30000] "Facebook" "Twitter" "Twitter" "Facebook" ...
$ number_of_notifications : num [1:30000] 61 59 57 59 66 50 60 49 57 64 ...
$ work_hours_per_day : num [1:30000] 6.75 9.17 7.91 6.36 6.21 ...
$ perceived_productivity_score : num [1:30000] 8.04 5.06 3.86 2.92 8.87 ...
$ actual_productivity_score : num [1:30000] 7.29 5.17 3.47 1.77 NA ...
$ stress_level : num [1:30000] 4 7 4 6 7 5 7 4 4 3 ...
$ sleep_hours : num [1:30000] 5.12 5.1 8.58 6.05 5.41 ...
$ screen_time_before_sleep : num [1:30000] 0.419 0.672 0.624 1.205 1.876 ...
$ breaks_during_work : num [1:30000] 8 7 0 1 1 5 4 2 10 10 ...
$ uses_focus_apps : logi [1:30000] FALSE TRUE TRUE FALSE FALSE FALSE ...
$ has_digital_wellbeing_enabled : logi [1:30000] FALSE TRUE FALSE FALSE TRUE TRUE ...
$ coffee_consumption_per_day : num [1:30000] 4 2 3 0 1 5 4 4 2 1 ...
$ days_feeling_burnout_per_month: num [1:30000] 11 25 17 4 30 2 20 29 10 18 ...
$ weekly_offline_hours : num [1:30000] 21.9 0 10.3 23.9 10.7 ...
$ job_satisfaction_score : num [1:30000] 6.34 3.41 2.47 1.73 9.69 ...
- attr(*, "spec")=
.. cols(
.. age = col_double(),
.. gender = col_character(),
.. job_type = col_character(),
.. daily_social_media_time = col_double(),
.. social_platform_preference = col_character(),
.. number_of_notifications = col_double(),
.. work_hours_per_day = col_double(),
.. perceived_productivity_score = col_double(),
.. actual_productivity_score = col_double(),
.. stress_level = col_double(),
.. sleep_hours = col_double(),
.. screen_time_before_sleep = col_double(),
.. breaks_during_work = col_double(),
.. uses_focus_apps = col_logical(),
.. has_digital_wellbeing_enabled = col_logical(),
.. coffee_consumption_per_day = col_double(),
.. days_feeling_burnout_per_month = col_double(),
.. weekly_offline_hours = col_double(),
.. job_satisfaction_score = col_double()
.. )
- attr(*, "problems")=<externalptr>
colSums(is.na(df))
age gender job_type daily_social_media_time
0 0 0 2765
social_platform_preference number_of_notifications work_hours_per_day perceived_productivity_score
0 0 0 1614
actual_productivity_score stress_level sleep_hours screen_time_before_sleep
2365 1904 2598 2211
breaks_during_work uses_focus_apps has_digital_wellbeing_enabled coffee_consumption_per_day
0 0 0 0
days_feeling_burnout_per_month weekly_offline_hours job_satisfaction_score
0 0 2730
df <- df %>% rename(
"job" = "job_type",
"online_hours" = "daily_social_media_time",
"app" = "social_platform_preference" ,
"notifications" = "number_of_notifications",
"work_hours" = "work_hours_per_day",
"self_prod_score" = "perceived_productivity_score",
"actual_prod_score" = "actual_productivity_score",
"stress" = "stress_level",
"focus_app" = "uses_focus_apps",
"digital_wellbeing" = "has_digital_wellbeing_enabled",
"coffee" = "coffee_consumption_per_day",
"burnout_days" = "days_feeling_burnout_per_month",
"job_score" = "job_satisfaction_score"
)
cols_to_fill <- c("online_hours", "self_prod_score", "actual_prod_score", "stress", "sleep_hours", "screen_time_before_sleep", "job_score") # Replace with your column names
for (col in cols_to_fill) {
df[[col]][is.na(df[[col]])] <- mean(df[[col]], na.rm = TRUE)
}
colSums(is.na(df))
age gender job online_hours app
0 0 0 0 0
notifications work_hours self_prod_score actual_prod_score stress
0 0 0 0 0
sleep_hours screen_time_before_sleep breaks_during_work focus_app digital_wellbeing
0 0 0 0 0
coffee burnout_days weekly_offline_hours job_score
0 0 0 0
cols_to_round <- c("self_prod_score", "actual_prod_score", "job_score")
for (col in cols_to_round) {
df[[col]] <- round(df[[col]])
}
head(df)
df <- df[df$gender != "Other", ]
ggplot(df, aes(x = `gender`)) +
geom_bar(fill = "cyan", color = "black", alpha = 0.5 , stat = "count") +
labs(title = "Gender Distribution", x = "Gender", y = "Frequency")
ggplot(df, aes(x = `job`)) +
geom_bar(fill = "green", color = "black", alpha = 0.5) +
labs(title = "Job Distribution", x = "Job", y = "Frequency")
ggplot(df, aes(x = `focus_app`)) +
geom_bar(fill = "brown", color = "black", alpha = 0.5) +
labs(title = "Focus App Users", x = "Yes or No", y = "Frequency")
ggplot(df, aes(x = `digital_wellbeing`)) +
geom_bar(fill = "red", color = "black", alpha = 0.5) +
labs(title = "Digital Wellbeing Enabled", x = "Yes or No", y = "Frequency")
ggplot(df, aes(x = `app`)) +
geom_bar(fill = "purple", color = "black", alpha = 0.5 , stat = "count") +
labs(title = "Social Media Platform Distribution", x = "App", y = "Frequency")
ggplot(df, aes(x = `age`)) +
geom_density(fill = "yellow", color = "black", alpha = 0.5) +
labs(title = "Age", x = "Age", y = "Frequency")
df <- df %>%
mutate(age_group = cut(
age,
breaks = c(17, 30, 47, 65),
labels = c("Young Adult", "Middle-Aged Adults", "Old Adults"),
right = TRUE,
include.lowest = TRUE
))
age_counts <- table(df$age_group)
pct <- round(100 * age_counts / sum(age_counts), 1)
labels <- paste(names(age_counts), "\n", pct, "%")
pie(age_counts, labels = labels, main = "Age Group Distribution")
ggplot(df, aes(x = `self_prod_score`)) +
geom_histogram(binwidth = 1, fill = "cyan", color = "black", alpha = 0.5) +
scale_x_continuous(breaks = 1:10) +
labs(title = "Self Productivity Score", x = "Self Productivity Score", y = "Frequency")
Registered S3 methods overwritten by 'htmltools':
method from
print.html tools:rstudio
print.shiny.tag tools:rstudio
print.shiny.tag.list tools:rstudio
Registered S3 method overwritten by 'rmarkdown':
method from
print.paged_df
ggplot(df, aes(x = `actual_prod_score`)) +
geom_histogram(binwidth = 1, fill = "green", color = "black", alpha = 0.5) +
scale_x_continuous(breaks = 1:10) +
labs(title = "Actual Prodcutivity Score", x = "Actual Productivity Score", y = "Frequency")
ggplot(df, aes(x = `sleep_hours`)) +
geom_density(fill = "red", color = "black", alpha = 0.5) +
labs(title = "Sleep Hours Distirbution", x = "Sleep Hours", y = "Frequency")
ggplot(df, aes(y = `work_hours`)) +
geom_boxplot(outlier.colour = "red", fill = "red", outlier.shape = 16) +
labs(title = "Boxplot of Sleep Hours", y = "Hours")
ggplot(df, aes(x = `work_hours`)) +
geom_density(fill = "cyan", color = "black", alpha = 0.5) +
labs(title = "Work Hours Distirbution", x = "Work Hours", y = "Frequency")
ggplot(df, aes(y = `work_hours`)) +
geom_boxplot(outlier.colour = "red", fill = "cyan", outlier.shape = 16) +
labs(title = "Boxplot of Work Hours", y = "Hours")
ggplot(df, aes(x = `online_hours`)) +
geom_density(fill = "pink", color = "black", alpha = 0.5) +
labs(title = "Online Hours Distirbution", x = "Online Hours", y = "Frequency")
ggplot(df, aes(y = `online_hours`)) +
geom_boxplot(outlier.colour = "red", fill = "pink", outlier.shape = 16) +
labs(title = "Boxplot of Online Hours", y = "Hours")
replace_outliers_with_mean <- function(data, columns) {
for (col in columns) {
Q1 <- quantile(data[[col]], 0.25, na.rm = TRUE)
Q3 <- quantile(data[[col]], 0.75, na.rm = TRUE)
IQR_val <- Q3 - Q1
lower_bound <- Q1 - 1.5 * IQR_val
upper_bound <- Q3 + 1.5 * IQR_val
mean_val <- mean(data[[col]], na.rm = TRUE)
data[[col]] <- ifelse(data[[col]] < lower_bound | data[[col]] > upper_bound,
mean_val,
data[[col]])
}
return(data)
}
df <- replace_outliers_with_mean(df, c("online_hours", "work_hours", "sleep_hours"))
ggplot(df, aes(y = `online_hours`)) +
geom_boxplot(outlier.colour = "red", fill = "pink", outlier.shape = 16) +
labs(title = "Boxplot of Online Hours", y = "Hours")
ggplot(df, aes(y = `work_hours`)) +
geom_boxplot(outlier.colour = "red", fill = "cyan", outlier.shape = 16) +
labs(title = "Boxplot of Work Hours", y = "Hours")
ggplot(df, aes(y = `work_hours`)) +
geom_boxplot(outlier.colour = "red", fill = "red", outlier.shape = 16) +
labs(title = "Boxplot of Sleep Hours", y = "Hours")
ggplot(df, aes(x = `stress`)) +
geom_histogram(binwidth = 1, fill = "green", color = "black", alpha = 0.5) +
scale_x_continuous(breaks = 1:10) +
labs(title = "Stress Level", x = "Stress Level", y = "Frequency")
ggplot(df, aes(x = `job_score`)) +
geom_histogram(binwidth = 1,fill = "purple", color = "black", alpha = 0.5) +
labs(title = "Job Satisfaction Score", x = "Job Satisfaction Score", y = "Frequency")
library(ggcorrplot)
corr_mat = round(cor(df[sapply(df, is.numeric)]),1)
ggcorrplot(corr_mat, lab = TRUE)
No strong correlation between features in dataset so predictive analysis won’t be feasible. so leaning towards hypothesis testing. We will be using t-test, anova to test some basic hypothesis.
H0: Average productivity score is equal to 6 Ha: Average productivity score is not equal to 6
t_test_productivity <- t.test(df$actual_prod_score, mu = 6)
print("T-Test Result of Actual Productivity Score")
[1] "T-Test Result of Actual Productivity Score"
print(t_test_productivity)
One Sample t-test
data: df$actual_prod_score
t = -96.371, df = 28821, p-value < 2.2e-16
alternative hypothesis: true mean is not equal to 6
95 percent confidence interval:
4.938242 4.980570
sample estimates:
mean of x
4.959406
H0: Use of focus apps have no effect on productivity Ha: Use of focus apps have effect on productivity
t_test_focus_app <- t.test(actual_prod_score ~ focus_app, data = df)
print("T-Test Result of Effect of Focus Apps")
[1] "T-Test Result of Effect of Focus Apps"
print(t_test_focus_app)
Welch Two Sample t-test
data: actual_prod_score by focus_app
t = 0.3019, df = 16341, p-value = 0.7627
alternative hypothesis: true difference in means between group FALSE and group TRUE is not equal to 0
95 percent confidence interval:
-0.03912522 0.05337156
sample estimates:
mean in group FALSE mean in group TRUE
4.961548 4.954425
H0:Screen Time is equal across various Social Media platforms Ha:Screen Time is not equal across various Social Media platforms
anova_model <- aov(online_hours ~ app, data = df)
summary(anova_model)
Df Sum Sq Mean Sq F value Pr(>F)
app 4 29 7.241 2.405 0.0473 *
Residuals 28817 86750 3.010
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
tukey <- TukeyHSD(anova_model)
par(mar = c(5, 9, 4, 2))
plot(tukey,las = 1)
H0 : Screen Time is equal across various Age group Ha : Screen Time is not equal across various Age group
anova_model <- aov(online_hours ~ age_group, data = df)
summary(anova_model)
Df Sum Sq Mean Sq F value Pr(>F)
age_group 2 2 1.209 0.402 0.669
Residuals 28819 86776 3.011
There is no significant affect of age group in screen time.
H0: There is no difference in mean Screen Time between groups that have digital well being enabled Ha: There is difference in mean Screen Time between groups that have digital well being enabled
t_test_digital_wellbeing <- t.test(online_hours ~ digital_wellbeing, data = df)
print("T Test Result of Digital Wellbeing")
[1] "T Test Result of Digital Wellbeing"
print(t_test_digital_wellbeing)
Welch Two Sample t-test
data: online_hours by digital_wellbeing
t = -0.53469, df = 12275, p-value = 0.5929
alternative hypothesis: true difference in means between group FALSE and group TRUE is not equal to 0
95 percent confidence interval:
-0.05878130 0.03358548
sample estimates:
mean in group FALSE mean in group TRUE
3.017930 3.030528