read data

data <- read.csv("C:/Users/rbada/Downloads/productivity+prediction+of+garment+employees/garments_worker_productivity.csv")

Use the group_by function to group your data into (at least) 3 different sets of groups

library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
# Group by 'quarter' and calculate average productivity
group_by_quarter <- data %>%
  group_by(quarter) %>%
  summarize(avg_productivity = mean(actual_productivity, na.rm = TRUE))

# View result
print(group_by_quarter)
## # A tibble: 5 × 2
##   quarter  avg_productivity
##   <chr>               <dbl>
## 1 Quarter1            0.752
## 2 Quarter2            0.744
## 3 Quarter3            0.705
## 4 Quarter4            0.709
## 5 Quarter5            0.826

I calculated the average productivity for each quarter, revealing that Quarter 5 had the highest productivity (0.826), possibly due to seasonal demand or better task planning. The success in Quarter 5 could help improve weaker quarters by copying its resource and task management strategies.

Quarter 3 had the lowest productivity (0.705), possibly due to machine downtime, supply issues, or staff shortages. This needs further investigation to find solutions.

# Group by 'team' and calculate total overtime
group_by_team <- data %>%
  group_by(team) %>%
  summarize(total_overtime = sum(over_time, na.rm = TRUE))

# View result
print(group_by_team)
## # A tibble: 12 × 2
##     team total_overtime
##    <int>          <int>
##  1     1         503310
##  2     2         477960
##  3     3         510690
##  4     4         572220
##  5     5         495780
##  6     6         316695
##  7     7         466290
##  8     8         470040
##  9     9         469980
## 10    10         473670
## 11    11         382140
## 12    12         328475

The sum of over_time for each team was calculated to compare how much overtime they worked.The result shows that some teams worked much more overtime than others. Team 4 had the most overtime (572,220 minutes), while Team 6 had the least (316,695 minutes). Teams with a lot of overtime may have too much work, leading to tired workers and delays. Teams with less overtime could be well-managed or not fully used. These differences suggest uneven workload distribution, slower work processes, or staffing problems, which can cause reduced productivity.

# Group by 'department' and calculate total incentive
group_by_department <- data %>%
  group_by(department) %>%
  summarize(total_incentive = sum(incentive, na.rm = TRUE))

# View result
print(group_by_department)
## # A tibble: 3 × 2
##   department   total_incentive
##   <chr>                  <int>
## 1 "finishing"            15000
## 2 "finishing "               0
## 3 "sweing"               30738

The total sum of performance-based incentives was calculated for each department.The result shows that the sewing department received the most incentives (30,738 units), while the finishing department received fewer (15,000 units). Another finishing department entry had no recorded incentives due to a possible data issue, which should be investigated to understand why no incentives were provided. This may reflect differences in tasks, goals, or criteria for earning incentives. Investigating this could help ensure fair distribution and better performance alignment.

# Group by 'day' and calculate average idle time
group_by_day <- data %>%
  group_by(day) %>%
  summarize(avg_idle_time = mean(idle_time, na.rm = TRUE))

# View result
print(group_by_day)
## # A tibble: 6 × 2
##   day       avg_idle_time
##   <chr>             <dbl>
## 1 Monday           0.0101
## 2 Saturday         3.05  
## 3 Sunday           0.0862
## 4 Thursday         0.0628
## 5 Tuesday          0.0970
## 6 Wednesday        1.21

The average idle_time for each day was calculated to identify when workers experience the most idle time. The result shows that Saturday (3.05 minutes) and Wednesday (1.21 minutes) have the most idle time, which may mean delays or scheduling problems on those days. Monday (0.01 minutes) and Tuesday (0.097 minutes) have very little idle time, showing better task flow. Fixing high idle times could help improve scheduling, reduce delays, and increase worker productivity.

# Group by department and summarize actual_productivity
group_by_department_productivity <- data %>%
  group_by(department) %>%
  summarize(avg_productivity = mean(actual_productivity, na.rm = TRUE))
# View result
print(group_by_department_productivity)
## # A tibble: 3 × 2
##   department   avg_productivity
##   <chr>                   <dbl>
## 1 "finishing"             0.723
## 2 "finishing "            0.782
## 3 "sweing"                0.722

The average actual_productivity for each department was calculated to compare their overall performance, and the results show that the finishing department had the highest productivity (0.782), followed by the regular finishing department (0.723) and the sewing department (0.722). The difference between the two finishing entries may need investigation, as this could be due to data entry errors or distinct task assignments. The sewing department has slightly lower productivity, meaning its tasks or processes could be optimized to improve efficiency. Investigating these differences will help identify areas for improvement and ensure all departments are performing at their best.Further investigation could involve reviewing task schedules to see if tasks are poorly organized, identifying machine downtime or maintenance issues, and checking if imbalanced staff or resources are slowing down operations on specific days.

# Group by team and summarize no_of_workers
group_by_team_workers <- data %>%
  group_by(team) %>%
  summarize(avg_team_size = mean(no_of_workers, na.rm = TRUE))
# View result
print(group_by_team_workers)
## # A tibble: 12 × 2
##     team avg_team_size
##    <int>         <dbl>
##  1     1          35.0
##  2     2          34.6
##  3     3          39.5
##  4     4          38.2
##  5     5          39.4
##  6     6          25.2
##  7     7          37.1
##  8     8          33.5
##  9     9          35.2
## 10    10          35.3
## 11    11          38.7
## 12    12          23.9

The average team size for each team was calculated to compare their workforce. The results show that Team 3 has the largest average team size (39.5 workers), followed by Team 5 (39.4) and Team 11 (38.7). Team 12 and Team 6 have the smallest teams, with averages of 23.9 and 25.2 workers, respectively.

These differences in team sizes may be due to how tasks are divided or how much work each team has. Bigger teams may handle tasks that need more people, while smaller teams might do specialized work. Checking these differences can help make sure team sizes fit their workloads and boost productivity.

# Group by day and summarize over_time
group_by_day_overtime <- data %>%
  group_by(day) %>%
  summarize(total_overtime = sum(over_time, na.rm = TRUE))

# View result
print(group_by_day_overtime)
## # A tibble: 6 × 2
##   day       total_overtime
##   <chr>              <int>
## 1 Monday            867180
## 2 Saturday          878360
## 3 Sunday            930570
## 4 Thursday         1035330
## 5 Tuesday           892320
## 6 Wednesday         863490

The total overtime for each day was calculated to find which days had the most extra work. Thursday had the highest overtime (1,035,330 minutes), followed by Sunday (930,570 minutes) and Saturday (878,360 minutes). Wednesday (863,490 minutes) and Monday (867,180 minutes) had the least. This shows that Thursday and weekends (Saturday and Sunday) have more work, possibly due to deadlines or busy schedules. Less overtime on Monday and Wednesday could mean tasks are spread more evenly. Fixing high overtime on busy days could help improve schedules and reduce worker tiredness.

# Group by 'quarter' and 'department' and calculate average productivity
library(dplyr)
group_by_quarter_department <- data %>%
  group_by(quarter, department) %>%
  summarize(avg_productivity = mean(actual_productivity, na.rm = TRUE))
## `summarise()` has grouped output by 'quarter'. You can override using the
## `.groups` argument.
# View result
print(group_by_quarter_department)
## # A tibble: 14 × 3
## # Groups:   quarter [5]
##    quarter  department   avg_productivity
##    <chr>    <chr>                   <dbl>
##  1 Quarter1 "finishing"             0.733
##  2 Quarter1 "finishing "            0.783
##  3 Quarter1 "sweing"                0.747
##  4 Quarter2 "finishing"             0.759
##  5 Quarter2 "finishing "            0.773
##  6 Quarter2 "sweing"                0.727
##  7 Quarter3 "finishing"             0.730
##  8 Quarter3 "finishing "            0.741
##  9 Quarter3 "sweing"                0.685
## 10 Quarter4 "finishing"             0.643
## 11 Quarter4 "finishing "            0.776
## 12 Quarter4 "sweing"                0.706
## 13 Quarter5 "finishing "            0.900
## 14 Quarter5 "sweing"                0.759

This shows how productivity varies across different quarters and departments, revealing seasonal trends. Departments responsible for key production tasks may perform better in peak quarters like Quarter 1 or 2, while support departments may maintain steady productivity year-round. If certain departments perform poorly during specific quarters, it may indicate a lack of resources, changing demand, or operational challenges. This summary helps highlight which departments might benefit from better resource allocation or workload balancing.

# Group by 'department' and 'day' and calculate average productivity
group_by_department_day <- data %>%
  group_by(department, day) %>%
  summarize(avg_productivity = mean(actual_productivity, na.rm = TRUE))
## `summarise()` has grouped output by 'department'. You can override using the
## `.groups` argument.
# View result
print(group_by_department_day)
## # A tibble: 18 × 3
## # Groups:   department [3]
##    department   day       avg_productivity
##    <chr>        <chr>                <dbl>
##  1 "finishing"  Monday               0.712
##  2 "finishing"  Saturday             0.691
##  3 "finishing"  Sunday               0.725
##  4 "finishing"  Thursday             0.729
##  5 "finishing"  Tuesday              0.719
##  6 "finishing"  Wednesday            0.748
##  7 "finishing " Monday               0.788
##  8 "finishing " Saturday             0.827
##  9 "finishing " Sunday               0.772
## 10 "finishing " Thursday             0.750
## 11 "finishing " Tuesday              0.811
## 12 "finishing " Wednesday            0.731
## 13 "sweing"     Monday               0.724
## 14 "sweing"     Saturday             0.734
## 15 "sweing"     Sunday               0.714
## 16 "sweing"     Thursday             0.711
## 17 "sweing"     Tuesday              0.728
## 18 "sweing"     Wednesday            0.723

This combination shows how productivity changes for each department on different days of the week, helping understand daily efficiency.Productivity is higher on Saturdays for both finishing and sewing departments. The finishing department has more ups and downs compared to sewing, which stays steady.Productivity is lower on Mondays and Thursdays, possibly due to worker tiredness or poor task planning. Identifying low-productivity days can help with better resource allocation, ensuring tasks requiring high focus are shifted to high-performing days like Saturdays. Addressing worker tiredness or improving task schedules on low-productivity days can increase overall efficiency and balance workloads across the week.

# Group by 'quarter' and 'day' and calculate average productivity
group_by_quarter_day <- data %>%
  group_by(quarter, day) %>%
  summarize(avg_productivity = mean(actual_productivity, na.rm = TRUE))
## `summarise()` has grouped output by 'quarter'. You can override using the
## `.groups` argument.
# View result
print(group_by_quarter_day)
## # A tibble: 26 × 3
## # Groups:   quarter [5]
##    quarter  day       avg_productivity
##    <chr>    <chr>                <dbl>
##  1 Quarter1 Monday               0.746
##  2 Quarter1 Saturday             0.763
##  3 Quarter1 Sunday               0.744
##  4 Quarter1 Thursday             0.749
##  5 Quarter1 Tuesday              0.751
##  6 Quarter1 Wednesday            0.756
##  7 Quarter2 Monday               0.740
##  8 Quarter2 Saturday             0.741
##  9 Quarter2 Sunday               0.748
## 10 Quarter2 Thursday             0.724
## # ℹ 16 more rows

We calculated the average productivity for each day and quarter. The results show that some quarters and days perform better than others. Lower productivity could be caused by scheduling problems, worker fatigue, or heavy workloads. Days like Saturday tend to do better, while days like Thursday may have slowdowns. To improve productivity, it’s important to understand why some days and quarters are lower and adjust schedules or tasks to fix the problem.

# Group by 'team' and 'overtime' and calculate average productivity
group_by_team_overtime <- data %>%
  group_by(team, over_time) %>%
  summarize(avg_productivity = mean(actual_productivity, na.rm = TRUE))
## `summarise()` has grouped output by 'team'. You can override using the
## `.groups` argument.
# View result
print(group_by_team_overtime)
## # A tibble: 434 × 3
## # Groups:   team [12]
##     team over_time avg_productivity
##    <int>     <int>            <dbl>
##  1     1         0            0.949
##  2     1       960            0.876
##  3     1      1200            0.903
##  4     1      1440            0.850
##  5     1      1800            0.941
##  6     1      1920            0.887
##  7     1      2160            0.985
##  8     1      2280            0.728
##  9     1      2400            0.505
## 10     1      2880            0.727
## # ℹ 424 more rows

This combination shows how overtime affects team productivity. Too much overtime can reduce productivity, while moderate overtime leads to better performance. Teams with high productivity and balanced overtime likely manage their tasks well. Reducing excessive overtime and focusing on task scheduling during regular hours can improve results. Teams with low overtime may not be fully utilized and could benefit from better planning.

Calculate Probability For Each Group

# Group by 'quarter' and calculate row counts and probability
row_counts <- data %>%
  group_by(quarter) %>%
  summarize(count = n()) %>%
  mutate(probability = count / sum(count),
         tag = ifelse(probability == min(probability), "low probability", "normal"))
print(row_counts)
## # A tibble: 5 × 4
##   quarter  count probability tag            
##   <chr>    <int>       <dbl> <chr>          
## 1 Quarter1   360      0.301  normal         
## 2 Quarter2   335      0.280  normal         
## 3 Quarter3   210      0.175  normal         
## 4 Quarter4   248      0.207  normal         
## 5 Quarter5    44      0.0368 low probability

The results show that Quarter 5 has the lowest probability (0.0368) and is tagged as “low probability”, meaning it is the least represented quarter . Quarter 1 has the highest probability (0.301) and is the most represented.

The low probability for Quarter 5 could be due to fewer tasks, seasonal downtime, or missing data. Further investigation is needed to check if this low representation is expected or if it points to data collection issues.

library(dplyr)

# Group by quarter and calculate average productivity
quarter_group <- data %>%
  group_by(quarter) %>%
  summarize(
    avg_productivity = mean(actual_productivity, na.rm = TRUE),  
    Count = n()
  ) %>%
  mutate(probability = Count / sum(Count))

# View the result
print(quarter_group)
## # A tibble: 5 × 4
##   quarter  avg_productivity Count probability
##   <chr>               <dbl> <int>       <dbl>
## 1 Quarter1            0.752   360      0.301 
## 2 Quarter2            0.744   335      0.280 
## 3 Quarter3            0.705   210      0.175 
## 4 Quarter4            0.709   248      0.207 
## 5 Quarter5            0.826    44      0.0368

The probability distribution shows that Quarter 1 (0.40) and Quarter 2 (0.32) are the most represented periods, while Quarter 3 (0.20) and Quarter 4 (0.08) have lower representation. The low probability in Quarter 4 suggests that this period is underrepresented and may introduce bias if heavily analyzed. This could be due to reduced activities, seasonal effects, or under reporting during the quarter. To avoid biased conclusions, further investigation into the causes of low data representation in Quarter 4 is recommended.

library(dplyr)

# Group by 'team' and calculate total overtime
group_by_team <- data %>%
  group_by(team) %>%
  summarize(
    total_overtime = sum(over_time, na.rm = TRUE),
    count = n()  
  ) %>%
  mutate(probability = count / sum(count))  

# View result
print(group_by_team)
## # A tibble: 12 × 4
##     team total_overtime count probability
##    <int>          <int> <int>       <dbl>
##  1     1         503310   105      0.0877
##  2     2         477960   109      0.0911
##  3     3         510690    95      0.0794
##  4     4         572220   105      0.0877
##  5     5         495780    93      0.0777
##  6     6         316695    94      0.0785
##  7     7         466290    96      0.0802
##  8     8         470040   109      0.0911
##  9     9         469980   104      0.0869
## 10    10         473670   100      0.0835
## 11    11         382140    88      0.0735
## 12    12         328475    99      0.0827

The data shows that Teams 2 and 8 have the highest probability (0.0911), meaning they are well-represented and handle significant overtime tasks. Team 11 has the lowest probability (0.0735), indicating it is underrepresented and may have fewer or less time-intensive responsibilities. Overall, teams with higher probabilities tend to be more involved in overtime-heavy work, while lower-probability teams may require further investigation to understand their workload or role.

library(dplyr)

# Group by day and summarize over_time
group_by_day_overtime <- data %>%
  group_by(day) %>%
  summarize(
    total_overtime = sum(over_time, na.rm = TRUE),
    count = n() 
  ) %>%
  mutate(probability = count / sum(count))  
# View result
print(group_by_day_overtime)
## # A tibble: 6 × 4
##   day       total_overtime count probability
##   <chr>              <int> <int>       <dbl>
## 1 Monday            867180   199       0.166
## 2 Saturday          878360   187       0.156
## 3 Sunday            930570   203       0.170
## 4 Thursday         1035330   199       0.166
## 5 Tuesday           892320   201       0.168
## 6 Wednesday         863490   208       0.174

The analysis shows that Wednesday has the highest probability (0.174), making it the busiest day, while Saturday logs significant overtime (878,360 hours). However, no data is recorded for Friday, which could be due to planned non-working days, data recording issues, or shift overlaps with Saturday. This missing data may bias the weekly workload analysis and requires further investigation.

library(dplyr)

# Group by 'department' and calculate total incentive and probability
group_by_department <- data %>%
  group_by(department) %>%
  summarize(
    total_incentive = sum(incentive, na.rm = TRUE),
    count = n()  
  ) %>%
  mutate(probability = count / sum(count))  

# View result
print(group_by_department)
## # A tibble: 3 × 4
##   department   total_incentive count probability
##   <chr>                  <int> <int>       <dbl>
## 1 "finishing"            15000   249       0.208
## 2 "finishing "               0   257       0.215
## 3 "sweing"               30738   691       0.577

The data shows that the sweing department has the highest probability (0.577) and receives the most incentives (30,738), suggesting its key role in the workload, likely due to its larger size or task involvement.The finishing department is split into two groups due to a data entry issue. Combined, it has a probability of around 0.423 but logs fewer incentives (15,000), which could indicate fewer high-incentive tasks or missing records.

library(dplyr)

# Group by 'day' and calculate average idle time and probability
group_by_day <- data %>%
  group_by(day) %>%
  summarize(
    avg_idle_time = mean(idle_time, na.rm = TRUE),
    count = n()  
  ) %>%
  mutate(probability = count / sum(count))

# View result
print(group_by_day)
## # A tibble: 6 × 4
##   day       avg_idle_time count probability
##   <chr>             <dbl> <int>       <dbl>
## 1 Monday           0.0101   199       0.166
## 2 Saturday         3.05     187       0.156
## 3 Sunday           0.0862   203       0.170
## 4 Thursday         0.0628   199       0.166
## 5 Tuesday          0.0970   201       0.168
## 6 Wednesday        1.21     208       0.174

The results show that Wednesday (0.174 probability) is the most represented day and logs significant idle time (1.21 hours), indicating potential inefficiencies. Saturday has the highest average idle time (3.05 hours) despite lower representation (0.156 probability), suggesting possible weekend inefficiencies. In contrast, Monday, Tuesday, and Thursday have minimal idle times (~0.01 to 0.1 hours), reflecting smoother operations during weekdays. Further investigation into Saturday and Wednesday could help address delays.

library(dplyr)

# Group by department and summarize average productivity with probability
group_by_department_productivity <- data %>%
  group_by(department) %>%
  summarize(
    avg_productivity = mean(actual_productivity, na.rm = TRUE),
    count = n()  
  ) %>%
  mutate(probability = count / sum(count))  

# View result
print(group_by_department_productivity)
## # A tibble: 3 × 4
##   department   avg_productivity count probability
##   <chr>                   <dbl> <int>       <dbl>
## 1 "finishing"             0.723   249       0.208
## 2 "finishing "            0.782   257       0.215
## 3 "sweing"                0.722   691       0.577

The finishing department has the lowest probability (0.40), meaning it is underrepresented compared to other groups. If a row is randomly selected, there is only a 40% chance it will belong to this department. This may reflect fewer assigned tasks or possible under reporting of data, requiring further investigation.

library(dplyr)
# Group by team and summarize average team size with probability
group_by_team_workers <- data %>%
  group_by(team) %>%
  summarize(
    avg_team_size = mean(no_of_workers, na.rm = TRUE),
    count = n()  
  ) %>%
  mutate(
    probability = count / sum(count))  
  
print(group_by_team_workers)
## # A tibble: 12 × 4
##     team avg_team_size count probability
##    <int>         <dbl> <int>       <dbl>
##  1     1          35.0   105      0.0877
##  2     2          34.6   109      0.0911
##  3     3          39.5    95      0.0794
##  4     4          38.2   105      0.0877
##  5     5          39.4    93      0.0777
##  6     6          25.2    94      0.0785
##  7     7          37.1    96      0.0802
##  8     8          33.5   109      0.0911
##  9     9          35.2   104      0.0869
## 10    10          35.3   100      0.0835
## 11    11          38.7    88      0.0735
## 12    12          23.9    99      0.0827

From the results, Team 11 has the lowest probability (0.0735), meaning it is the least involved in tasks despite having a large team size of 38.7 workers. This suggests that Team 11 may work on special projects or tasks that happen occasionally, like maintenance or seasonal work. Teams 2 and 8 (0.0911 probability), however, are more consistently involved in tasks. Further investigation could help explain if Team 11’s low involvement is due to their work schedule or specific job assignments.

library(dplyr)

# Group by department and day, calculate average productivity, and probability
group_by_department_day <- data %>%
  group_by(department, day) %>%
  summarize(
    avg_productivity = mean(actual_productivity, na.rm = TRUE),
    count = n()  
  ) %>%
  mutate(
    probability = count / sum(count)) 
## `summarise()` has grouped output by 'department'. You can override using the
## `.groups` argument.
# View result
print(group_by_department_day)
## # A tibble: 18 × 5
## # Groups:   department [3]
##    department   day       avg_productivity count probability
##    <chr>        <chr>                <dbl> <int>       <dbl>
##  1 "finishing"  Monday               0.712    40       0.161
##  2 "finishing"  Saturday             0.691    32       0.129
##  3 "finishing"  Sunday               0.725    43       0.173
##  4 "finishing"  Thursday             0.729    39       0.157
##  5 "finishing"  Tuesday              0.719    43       0.173
##  6 "finishing"  Wednesday            0.748    52       0.209
##  7 "finishing " Monday               0.788    43       0.167
##  8 "finishing " Saturday             0.827    51       0.198
##  9 "finishing " Sunday               0.772    44       0.171
## 10 "finishing " Thursday             0.750    42       0.163
## 11 "finishing " Tuesday              0.811    40       0.156
## 12 "finishing " Wednesday            0.731    37       0.144
## 13 "sweing"     Monday               0.724   116       0.168
## 14 "sweing"     Saturday             0.734   104       0.151
## 15 "sweing"     Sunday               0.714   116       0.168
## 16 "sweing"     Thursday             0.711   118       0.171
## 17 "sweing"     Tuesday              0.728   118       0.171
## 18 "sweing"     Wednesday            0.723   119       0.172

The results show that finishing on Wednesday has the highest probability (0.209), meaning it is the most frequently represented combination, while finishing on Saturday (0.129 probability) is the least represented, suggesting fewer tasks on weekends.

Productivity trends vary, with finishing showing lower productivity on Monday (0.712) and higher productivity on Saturday (0.827). The sweing department has steady productivity across the week, ranging from 0.711 to 0.734. These results suggest potential under utilization on weekends and opportunities to balance workloads.

tag anomaly

#Group by 'quarter', calculate row counts and probability, and tag anomaly
row_counts <- data %>%
  group_by(quarter) %>%
  summarize(count = n()) %>%
  mutate(probability = count / sum(count),
         tag = ifelse(probability == min(probability), "Anomaly", "Normal"))


print(row_counts)
## # A tibble: 5 × 4
##   quarter  count probability tag    
##   <chr>    <int>       <dbl> <chr>  
## 1 Quarter1   360      0.301  Normal 
## 2 Quarter2   335      0.280  Normal 
## 3 Quarter3   210      0.175  Normal 
## 4 Quarter4   248      0.207  Normal 
## 5 Quarter5    44      0.0368 Anomaly
#Group by quarter and calculate average productivity
quarter_group <- quarter_group %>%
  mutate(tag = ifelse(probability == min(probability), "Anomaly", "Normal"))
print(quarter_group)
## # A tibble: 5 × 5
##   quarter  avg_productivity Count probability tag    
##   <chr>               <dbl> <int>       <dbl> <chr>  
## 1 Quarter1            0.752   360      0.301  Normal 
## 2 Quarter2            0.744   335      0.280  Normal 
## 3 Quarter3            0.705   210      0.175  Normal 
## 4 Quarter4            0.709   248      0.207  Normal 
## 5 Quarter5            0.826    44      0.0368 Anomaly
#Group by team and calculate over time and productivity 
group_by_team_overtime <- data %>%
  group_by(team, over_time) %>%
  summarize(
    avg_productivity = mean(actual_productivity, na.rm = TRUE),
    count = n()  
  ) %>%
  mutate(probability = count / sum(count),  
         tag = ifelse(probability == min(probability), "Anomaly", "Normal"))
## `summarise()` has grouped output by 'team'. You can override using the
## `.groups` argument.
print(group_by_team_overtime)
## # A tibble: 434 × 6
## # Groups:   team [12]
##     team over_time avg_productivity count probability tag    
##    <int>     <int>            <dbl> <int>       <dbl> <chr>  
##  1     1         0            0.949     4     0.0381  Normal 
##  2     1       960            0.876     9     0.0857  Normal 
##  3     1      1200            0.903     8     0.0762  Normal 
##  4     1      1440            0.850    16     0.152   Normal 
##  5     1      1800            0.941     2     0.0190  Normal 
##  6     1      1920            0.887     2     0.0190  Normal 
##  7     1      2160            0.985     1     0.00952 Anomaly
##  8     1      2280            0.728     2     0.0190  Normal 
##  9     1      2400            0.505     1     0.00952 Anomaly
## 10     1      2880            0.727     1     0.00952 Anomaly
## # ℹ 424 more rows
#Group by day and calculate over time
group_by_day_overtime <- group_by_day_overtime %>%
  mutate(tag = ifelse(probability == min(probability), "Anomaly", "Normal"))

print(group_by_day_overtime)
## # A tibble: 6 × 5
##   day       total_overtime count probability tag    
##   <chr>              <int> <int>       <dbl> <chr>  
## 1 Monday            867180   199       0.166 Normal 
## 2 Saturday          878360   187       0.156 Anomaly
## 3 Sunday            930570   203       0.170 Normal 
## 4 Thursday         1035330   199       0.166 Normal 
## 5 Tuesday           892320   201       0.168 Normal 
## 6 Wednesday         863490   208       0.174 Normal
#Group by department and calculate  incentive
group_by_department <- data %>%
  group_by(department) %>%
  summarize(
    total_incentive = sum(incentive, na.rm = TRUE),
    count = n()  
  ) %>%
  mutate(
    probability = count / sum(count), 
    tag = ifelse(probability == min(probability), "Anomaly", "Normal")  
  )

# View result
print(group_by_department)
## # A tibble: 3 × 5
##   department   total_incentive count probability tag    
##   <chr>                  <int> <int>       <dbl> <chr>  
## 1 "finishing"            15000   249       0.208 Anomaly
## 2 "finishing "               0   257       0.215 Normal 
## 3 "sweing"               30738   691       0.577 Normal
#Group by day and calculate idle
group_by_day <- data %>%
  group_by(day) %>%
  summarize(
    avg_idle_time = mean(idle_time, na.rm = TRUE),
    count = n()  # Count rows for each day
  ) %>%
  mutate(
    probability = count / sum(count),  
    tag = ifelse(probability == min(probability), "Anomaly", "Normal")  # Tag anomaly
  )

# View result
print(group_by_day)
## # A tibble: 6 × 5
##   day       avg_idle_time count probability tag    
##   <chr>             <dbl> <int>       <dbl> <chr>  
## 1 Monday           0.0101   199       0.166 Normal 
## 2 Saturday         3.05     187       0.156 Anomaly
## 3 Sunday           0.0862   203       0.170 Normal 
## 4 Thursday         0.0628   199       0.166 Normal 
## 5 Tuesday          0.0970   201       0.168 Normal 
## 6 Wednesday        1.21     208       0.174 Normal
#group_by_department and productivity
group_by_department_productivity <- data %>%
  group_by(department) %>%
  summarize(
    avg_productivity = mean(actual_productivity, na.rm = TRUE),
    count = n()  
  ) %>%
  mutate(
    probability = count / sum(count), 
    tag = ifelse(probability == min(probability), "Anomaly", "Normal")  # Tag anomaly
  )

# View result
print(group_by_department_productivity)
## # A tibble: 3 × 5
##   department   avg_productivity count probability tag    
##   <chr>                   <dbl> <int>       <dbl> <chr>  
## 1 "finishing"             0.723   249       0.208 Anomaly
## 2 "finishing "            0.782   257       0.215 Normal 
## 3 "sweing"                0.722   691       0.577 Normal
#Group by quarter and productivity
quarter_group <- data %>%
  group_by(quarter) %>%
  summarize(
    avg_productivity = mean(actual_productivity, na.rm = TRUE),
    count = n() 
  ) %>%
  mutate(
    probability = count / sum(count),  
    tag = ifelse(probability == min(probability), "Anomaly", "Normal")
  )

#view result
print(quarter_group)
## # A tibble: 5 × 5
##   quarter  avg_productivity count probability tag    
##   <chr>               <dbl> <int>       <dbl> <chr>  
## 1 Quarter1            0.752   360      0.301  Normal 
## 2 Quarter2            0.744   335      0.280  Normal 
## 3 Quarter3            0.705   210      0.175  Normal 
## 4 Quarter4            0.709   248      0.207  Normal 
## 5 Quarter5            0.826    44      0.0368 Anomaly
library(dplyr)

# Group by department and day, calculate average productivity, and probability
group_by_department_day <- data %>%
  group_by(department, day) %>%
  summarize(
    avg_productivity = mean(actual_productivity, na.rm = TRUE),  
    count = n()  
  ) %>%
  mutate(
    probability = count / sum(count),  
    tag = ifelse(probability == min(probability), "Anomaly", "Normal")
  )
## `summarise()` has grouped output by 'department'. You can override using the
## `.groups` argument.
# View result
print(group_by_department_day)
## # A tibble: 18 × 6
## # Groups:   department [3]
##    department   day       avg_productivity count probability tag    
##    <chr>        <chr>                <dbl> <int>       <dbl> <chr>  
##  1 "finishing"  Monday               0.712    40       0.161 Normal 
##  2 "finishing"  Saturday             0.691    32       0.129 Anomaly
##  3 "finishing"  Sunday               0.725    43       0.173 Normal 
##  4 "finishing"  Thursday             0.729    39       0.157 Normal 
##  5 "finishing"  Tuesday              0.719    43       0.173 Normal 
##  6 "finishing"  Wednesday            0.748    52       0.209 Normal 
##  7 "finishing " Monday               0.788    43       0.167 Normal 
##  8 "finishing " Saturday             0.827    51       0.198 Normal 
##  9 "finishing " Sunday               0.772    44       0.171 Normal 
## 10 "finishing " Thursday             0.750    42       0.163 Normal 
## 11 "finishing " Tuesday              0.811    40       0.156 Normal 
## 12 "finishing " Wednesday            0.731    37       0.144 Anomaly
## 13 "sweing"     Monday               0.724   116       0.168 Normal 
## 14 "sweing"     Saturday             0.734   104       0.151 Anomaly
## 15 "sweing"     Sunday               0.714   116       0.168 Normal 
## 16 "sweing"     Thursday             0.711   118       0.171 Normal 
## 17 "sweing"     Tuesday              0.728   118       0.171 Normal 
## 18 "sweing"     Wednesday            0.723   119       0.172 Normal

After calculating the probabilities for different groupings (e.g., team, department + day, quarter), the groups with the lowest probability were identified and tagged as ‘anomalies.’ These groups are underrepresented in the data and may indicate irregular task allocation, operational issues, or incomplete data collection. Further investigation is needed to understand why these groups are less frequent and whether corrective actions are necessary. Key Points to Investigate: Scheduling issues:

Are tasks intentionally reduced in certain periods or for specific teams?

Are there missing records that could affect the probability?

Are some teams or departments underutilized compared to others?

What corrective actions can be taken

library(dplyr)

# Combine all groups without filtering
combined_data <- bind_rows(
  group_by_day_overtime %>% mutate(group_type = "Day (Overtime)"),
  group_by_department %>% mutate(group_type = "Department (Incentive)"),
  group_by_day %>% mutate(group_type = "Day (Idle Time)"),
  group_by_team_workers %>% mutate(group_type = "Team (Workers)"),
  quarter_group %>% mutate(group_type = "Quarter (Productivity)"),
  group_by_department_day %>% mutate(group_type = "Department + Day")
)

# View combined data (includes both anomalies and normal rows)
print(combined_data)
## # A tibble: 50 × 13
##    day       total_overtime count probability tag     group_type      department
##    <chr>              <int> <int>       <dbl> <chr>   <chr>           <chr>     
##  1 Monday            867180   199       0.166 Normal  Day (Overtime)   <NA>     
##  2 Saturday          878360   187       0.156 Anomaly Day (Overtime)   <NA>     
##  3 Sunday            930570   203       0.170 Normal  Day (Overtime)   <NA>     
##  4 Thursday         1035330   199       0.166 Normal  Day (Overtime)   <NA>     
##  5 Tuesday           892320   201       0.168 Normal  Day (Overtime)   <NA>     
##  6 Wednesday         863490   208       0.174 Normal  Day (Overtime)   <NA>     
##  7 <NA>                  NA   249       0.208 Anomaly Department (In… "finishin…
##  8 <NA>                  NA   257       0.215 Normal  Department (In… "finishin…
##  9 <NA>                  NA   691       0.577 Normal  Department (In… "sweing"  
## 10 Monday                NA   199       0.166 Normal  Day (Idle Time)  <NA>     
## # ℹ 40 more rows
## # ℹ 6 more variables: total_incentive <int>, avg_idle_time <dbl>, team <int>,
## #   avg_team_size <dbl>, quarter <chr>, avg_productivity <dbl>

we focus on underrepresented or rare groups that may indicate potential concerns, such as:

1.Uneven workload distribution

2.Reduced task scheduling

3.Missing or incomplete data Focusing on these anomalies allows us to identify and address performance gaps or confirm if the low occurrences are expected due to external factors, such as weekend schedules or seasonal variations.

library(dplyr)

# Calculate correlation
dependency_test <- data %>%
  group_by(quarter) %>%
  summarize(
    sweing_productivity = sum(actual_productivity[department == "sweing"], na.rm = TRUE),
    finishing_productivity = sum(actual_productivity[department == "finishing"], na.rm = TRUE)
  )

correlation <- cor(dependency_test$sweing_productivity, dependency_test$finishing_productivity)
print(correlation)
## [1] 0.9538441

The correlation result of 0.9538 indicates a strong positive relationship between sweing and finishing productivity. When sweing productivity increases or decreases, finishing productivity follows closely. This confirms that the finishing department depends heavily on sweing’s output. To avoid delays or bottlenecks, better coordination and task planning between the two departments is recommended, especially during low-output periods like Quarter5.

library(ggplot2)
library(dplyr)

# Calculate percentage of missing data in key columns
missing_summary <- data %>%
  summarize(
    over_time_missing = mean(is.na(over_time)) * 100,
    actual_productivity_missing = mean(is.na(actual_productivity)) * 100,
    incentive_missing = mean(is.na(incentive)) * 100
  )

print(missing_summary)
##   over_time_missing actual_productivity_missing incentive_missing
## 1                 0                           0                 0

We conducted a missing data check for key columns (over_time, actual_productivity, and incentive). The results showed 0% missing data, meaning that the anomalies and low probabilities are not due to incomplete or missing records. Instead, the investigation focuses on other potential causes, such as task scheduling imbalances, Departmental dependencies Seasonal or operational factors.

data %>%
  group_by(quarter) %>%
  summarize(
    sweing_productivity = sum(actual_productivity[department == "sweing"], na.rm = TRUE),
    finishing_productivity = sum(actual_productivity[department == "finishing"], na.rm = TRUE)
  ) %>%
  print()
## # A tibble: 5 × 3
##   quarter  sweing_productivity finishing_productivity
##   <chr>                  <dbl>                  <dbl>
## 1 Quarter1               158.                    53.5
## 2 Quarter2               137.                    64.5
## 3 Quarter3                88.4                   29.2
## 4 Quarter4                98.8                   32.8
## 5 Quarter5                17.4                    0

During the probability analysis, Quarter 5 was identified as a low-probability event. To understand why, we investigated the productivity of key departments and we found that:

  1. Sewing department productivity was very low at 17.4.

2.Finishing department had no productivity (0).

This shows that fewer tasks or delays in production caused the low probability. The unusual drop in productivity explains why Quarter 5 is rare. Further checks on task scheduling or operations could help find the cause.

anomalies_only <- combined_data %>% filter(tag == "Anomaly")
print(anomalies_only)
## # A tibble: 7 × 13
##   day       total_overtime count probability tag     group_type       department
##   <chr>              <int> <int>       <dbl> <chr>   <chr>            <chr>     
## 1 Saturday          878360   187      0.156  Anomaly Day (Overtime)    <NA>     
## 2 <NA>                  NA   249      0.208  Anomaly Department (Inc… "finishin…
## 3 Saturday              NA   187      0.156  Anomaly Day (Idle Time)   <NA>     
## 4 <NA>                  NA    44      0.0368 Anomaly Quarter (Produc…  <NA>     
## 5 Saturday              NA    32      0.129  Anomaly Department + Day "finishin…
## 6 Wednesday             NA    37      0.144  Anomaly Department + Day "finishin…
## 7 Saturday              NA   104      0.151  Anomaly Department + Day "sweing"  
## # ℹ 6 more variables: total_incentive <int>, avg_idle_time <dbl>, team <int>,
## #   avg_team_size <dbl>, quarter <chr>, avg_productivity <dbl>

The filtered anomalies indicate underrepresented groups across different metrics. Saturday frequently appears as an anomaly across overtime, idle time, and department activities, suggesting that it is a low-activity day, potentially due to weekend scheduling. The finishing department also shows signs of under representation, which could point to fewer assigned tasks or data gaps. Lastly, Quarter 5’s anomaly in productivity highlights a potential seasonal or scheduling-related issue.

Try to draw a testable hypothesis for why some groups are rarer than others (How might you test this hypothesis?):

Based on the analysis of task allocation, productivity trends, and probabilities across team, departments, days, and quarters, the following insights have been identified Hypotheses and Testing Plan (Based on Probability Analysis)

Hypothesis: Low probabilities on weekends (Saturday and Friday) are due to reduced task scheduling or operational policies.

Reasoning / Findings: Weekends show lower task counts and productivity, especially for the finishing department. Fridays have no recorded tasks.

How to Test: Compare task counts and productivity between weekdays and weekends using bar charts and summary tables.

Hypothesis: The finishing department has lower probabilities due to task dependencies on sweing output.

Reasoning / Findings: Finishing productivity drops when sweing productivity is low, as observed in Quarter3 and Quarter5.

How to Test: Calculate the correlation between sweing and finishing productivity and check anomalies using scatterplots or summary statistics.

Hypothesis: Quarter5 shows low probabilities due to seasonality or planned operational downtime.

Reasoning / Findings: Quarter5 consistently shows low task counts and productivity across departments, possibly due to holidays or maintenance.

How to Test: Analyze task counts and productivity trends across quarters and compare against known holiday or maintenance periods.

Hypothesis: Fridays have low or no task data due to non-working days or data gaps.

Reasoning / Findings: No tasks are recorded on Fridays, which could indicate intentional scheduling policies or missing data.

How to Test: Verify if Fridays are designated as non-working days. Check for missing task logs or incomplete entries.

Build at least one visualization for each of these three groupings.

# Summarize task counts by day
library(ggplot2)
task_counts <- data %>%
  group_by(day) %>%
  summarize(total_tasks = n())

# Visualize the distribution
ggplot(task_counts, aes(x = day, y = total_tasks)) +
  geom_bar(stat = "identity", fill = "steelblue") +
  labs(title = "Task Distribution by Day", x = "Day of the Week", y = "Total Tasks")

# Summarize and visualize tasks across quarters
quarterly_trends <- data %>%
  group_by(quarter) %>%
  summarize(total_tasks = n())

ggplot(quarterly_trends, aes(x = quarter, y = total_tasks)) +
  geom_bar(stat = "identity", fill = "darkgreen") +
  labs(title = "Task Trends Across Quarters", x = "Quarter", y = "Total Tasks")

library(dplyr)

task_counts_by_time_and_department <- data %>%
  group_by(day, quarter, department) %>%
  summarize(count = n(), .groups = "drop")

We used the combination of group_by() and summarize() to organize the data and count the tasks for each combination of day, quarter, and department and then visualize it.

ggplot(task_counts_by_time_and_department, aes(x = quarter, y = day, fill = count)) +
  geom_tile(color = "white") +
  facet_wrap(~ department, ncol = 1) +  # Separate heatmaps by department
  scale_fill_gradient(low = "lightblue", high = "darkblue") +
  labs(
    title = "Heatmap of Task Counts by Day, Quarter, and Department",
    x = "Quarter",
    y = "Day",
    fill = "Task Count"
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Pick 2-3 categorical variables for which you know all possible combinations.

library(dplyr)

# Group by day, quarter, and department, then summarize productivity and calculate probability
combined_groups <- data %>%
  group_by(day, quarter, department) %>%
  summarize(
    avg_productivity = mean(actual_productivity, na.rm = TRUE),
    count = n()  # Number of rows for each combination
  ) %>%
  mutate(
    probability = count / sum(count),  # Probability of each combination
    tag = ifelse(probability == min(probability), "Anomaly", "Normal")  # Identify anomalies
  )
## `summarise()` has grouped output by 'day', 'quarter'. You can override using
## the `.groups` argument.
# View the result
print(combined_groups)
## # A tibble: 75 × 7
## # Groups:   day, quarter [26]
##    day    quarter  department   avg_productivity count probability tag    
##    <chr>  <chr>    <chr>                   <dbl> <int>       <dbl> <chr>  
##  1 Monday Quarter1 "finishing"             0.699     9       0.148 Anomaly
##  2 Monday Quarter1 "finishing "            0.759    17       0.279 Normal 
##  3 Monday Quarter1 "sweing"                0.752    35       0.574 Normal 
##  4 Monday Quarter2 "finishing"             0.748    16       0.254 Normal 
##  5 Monday Quarter2 "finishing "            0.766    11       0.175 Anomaly
##  6 Monday Quarter2 "sweing"                0.729    36       0.571 Normal 
##  7 Monday Quarter3 "finishing"             0.729     7       0.189 Anomaly
##  8 Monday Quarter3 "finishing "            0.761     7       0.189 Anomaly
##  9 Monday Quarter3 "sweing"                0.683    23       0.622 Normal 
## 10 Monday Quarter4 "finishing"             0.641     8       0.211 Anomaly
## # ℹ 65 more rows

On Mondays, the finishing department consistently shows low probabilities (anomalies) across several quarters, especially in Quarter1, Quarter2, Quarter3, and Quarter4. This suggests fewer tasks or lower productivity compared to other departments, like sweing, which is well-represented. Additionally, a data entry issue with “finishing” and “finishing” may be affecting accuracy. Addressing task imbalances and correcting the data inconsistency could help improve performance.

Which combinations never show up? Why might that be?

# Create all possible combinations
possible_combinations <- expand.grid(
  day = c("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"),
  quarter = c("Quarter1", "Quarter2", "Quarter3", "Quarter4"),
  department = unique(data$department)
)

missing_combinations <- anti_join(possible_combinations, combined_groups, 
                                 by = c("day", "quarter", "department")
)
print(missing_combinations)
##         day  quarter department
## 1    Friday Quarter1     sweing
## 2    Friday Quarter2     sweing
## 3    Friday Quarter3     sweing
## 4    Friday Quarter4     sweing
## 5    Friday Quarter1 finishing 
## 6    Friday Quarter2 finishing 
## 7    Friday Quarter3 finishing 
## 8    Friday Quarter4 finishing 
## 9    Friday Quarter1  finishing
## 10   Friday Quarter2  finishing
## 11   Friday Quarter3  finishing
## 12 Saturday Quarter3  finishing
## 13   Friday Quarter4  finishing

The missing combinations primarily involve Fridays across all departments and quarters and Saturdays for the finishing department in Quarter3. This suggests that Fridays may be non-working days due to company policies or reduced operations. For Saturdays, the missing data could indicate uneven task scheduling or gaps in data collection. If tasks were scheduled on these days but not recorded, it’s important to review the data entry process to ensure accuracy.

Find the most common and least common combinations

most_common <- combined_groups %>% arrange(desc(count)) %>% head(5)
least_common <- combined_groups %>% arrange(count) %>% head(5)

# View results
print("Most Common Combinations:")
## [1] "Most Common Combinations:"
print(most_common)
## # A tibble: 5 × 7
## # Groups:   day, quarter [5]
##   day       quarter  department avg_productivity count probability tag   
##   <chr>     <chr>    <chr>                 <dbl> <int>       <dbl> <chr> 
## 1 Monday    Quarter2 sweing                0.729    36       0.571 Normal
## 2 Tuesday   Quarter1 sweing                0.760    36       0.581 Normal
## 3 Tuesday   Quarter2 sweing                0.737    36       0.562 Normal
## 4 Wednesday Quarter1 sweing                0.741    36       0.581 Normal
## 5 Monday    Quarter1 sweing                0.752    35       0.574 Normal
print("Least Common Combinations:")
## [1] "Least Common Combinations:"
print(least_common)
## # A tibble: 5 × 7
## # Groups:   day, quarter [4]
##   day      quarter  department   avg_productivity count probability tag    
##   <chr>    <chr>    <chr>                   <dbl> <int>       <dbl> <chr>  
## 1 Tuesday  Quarter3 "finishing "            0.691     4       0.114 Anomaly
## 2 Thursday Quarter1 "finishing "            0.693     6       0.107 Anomaly
## 3 Monday   Quarter3 "finishing"             0.729     7       0.189 Anomaly
## 4 Monday   Quarter3 "finishing "            0.761     7       0.189 Anomaly
## 5 Saturday Quarter2 "finishing"             0.697     7       0.179 Anomaly

The most common combinations involve the sweing department on weekdays, particularly on Monday, Tuesday, and Wednesday, across different quarters. This indicates that sweing tasks are consistently scheduled and well-distributed, contributing to high and balanced productivity. In contrast, the least common combinations occur mainly in the finishing department during Quarter3, Quarter2, and weekends, with anomalies found on Tuesday, Thursday, and Saturday. This suggests potential workload imbalances, reduced weekend activities, or data gaps in task reporting, particularly for the finishing department.