Purpose: Descriptive analysis of the complete ClaudePluginHub Skills dataset scraped from: https://www.claudepluginhub.com/
Main outputs: 1. Dataset profile 2. Data quality 3. Category analysis 4. Technology analysis 5. Popularity analysis 6. Text analysis 7. Author analysis 8. Correlation analysis 9. Popularity concentration 10. Gini coefficient 11. Slide-ready findings
install.packages(c(
"tidyverse",
"jsonlite",
"scales",
"janitor",
"lubridate",
"tidytext",
"wordcloud",
"RColorBrewer",
"knitr",
"kableExtra"
),
repos = "https://cloud.r-project.org")
## Installing packages into 'C:/Users/khanh/AppData/Local/R/win-library/4.6'
## (as 'lib' is unspecified)
## package 'tidyverse' successfully unpacked and MD5 sums checked
## package 'jsonlite' successfully unpacked and MD5 sums checked
## Warning: cannot remove prior installation of package 'jsonlite'
## Warning in file.copy(savedcopy, lib, recursive = TRUE): problem copying
## C:\Users\khanh\AppData\Local\R\win-library\4.6\00LOCK\jsonlite\libs\x64\jsonlite.dll
## to
## C:\Users\khanh\AppData\Local\R\win-library\4.6\jsonlite\libs\x64\jsonlite.dll:
## Permission denied
## Warning: restored 'jsonlite'
## package 'scales' successfully unpacked and MD5 sums checked
## package 'janitor' successfully unpacked and MD5 sums checked
## package 'lubridate' successfully unpacked and MD5 sums checked
## Warning: cannot remove prior installation of package 'lubridate'
## Warning in file.copy(savedcopy, lib, recursive = TRUE): problem copying
## C:\Users\khanh\AppData\Local\R\win-library\4.6\00LOCK\lubridate\libs\x64\lubridate.dll
## to
## C:\Users\khanh\AppData\Local\R\win-library\4.6\lubridate\libs\x64\lubridate.dll:
## Permission denied
## Warning: restored 'lubridate'
## package 'tidytext' successfully unpacked and MD5 sums checked
## package 'wordcloud' successfully unpacked and MD5 sums checked
## Warning: cannot remove prior installation of package 'wordcloud'
## Warning in file.copy(savedcopy, lib, recursive = TRUE): problem copying
## C:\Users\khanh\AppData\Local\R\win-library\4.6\00LOCK\wordcloud\libs\x64\wordcloud.dll
## to
## C:\Users\khanh\AppData\Local\R\win-library\4.6\wordcloud\libs\x64\wordcloud.dll:
## Permission denied
## Warning: restored 'wordcloud'
## package 'RColorBrewer' successfully unpacked and MD5 sums checked
## package 'knitr' successfully unpacked and MD5 sums checked
## package 'kableExtra' successfully unpacked and MD5 sums checked
##
## The downloaded binary packages are in
## C:\Users\khanh\AppData\Local\Temp\Rtmp2XL8WE\downloaded_packages
input_file <- "C:/Users/khanh/OneDrive/Desktop/GMU/PHD/ClaudePlugIn/code/claudepluginhub_data/skills.csv"
output_dir <- "output"
table_dir <- file.path(output_dir, "tables")
figure_dir <- file.path(output_dir, "figures")
dir.create(output_dir, showWarnings = FALSE)
dir.create(table_dir, showWarnings = FALSE)
dir.create(figure_dir, showWarnings = FALSE)
skills <- read_csv(
input_file,
show_col_types = FALSE
)
skills <- skills %>%
clean_names()
cat("\n====================================================\n")
##
## ====================================================
cat("CLAUDEPLUGINHUB SKILLS DATASET\n")
## CLAUDEPLUGINHUB SKILLS DATASET
cat("====================================================\n")
## ====================================================
cat("Rows:", nrow(skills), "\n")
## Rows: 282436
cat("Columns:", ncol(skills), "\n\n")
## Columns: 17
cat("Column names:\n")
## Column names:
print(names(skills))
## [1] "id" "component_id"
## [3] "name" "description"
## [5] "allowed_tools" "supporting_assets_count"
## [7] "plugin_id" "plugin_slug"
## [9] "plugin_name" "plugin_display_name"
## [11] "plugin_stars" "plugin_categories"
## [13] "usage_count" "enriched_technologies"
## [15] "enriched_topics" "name_key"
## [17] "variant_count"
dataset_profile <- tibble(
Metric = c(
"Number of skills",
"Number of variables",
"Duplicate rows",
"Total missing cells",
"Total cells"
),
Value = c(
nrow(skills),
ncol(skills),
sum(duplicated(skills)),
sum(is.na(skills)),
nrow(skills) * ncol(skills)
)
)
print(dataset_profile)
## # A tibble: 5 × 2
## Metric Value
## <chr> <int>
## 1 Number of skills 282436
## 2 Number of variables 17
## 3 Duplicate rows 0
## 4 Total missing cells 809223
## 5 Total cells 4801412
write_csv(
dataset_profile,
file.path(table_dir, "dataset_profile.csv")
)
data_types <- tibble(
Variable = names(skills),
Data_Type = sapply(
skills,
function(x) class(x)[1]
),
Non_Missing = sapply(
skills,
function(x) sum(!is.na(x))
),
Missing = sapply(
skills,
function(x) sum(is.na(x))
),
Missing_Percentage = sapply(
skills,
function(x) mean(is.na(x)) * 100
),
Unique_Values = sapply(
skills,
function(x) n_distinct(x, na.rm = TRUE)
)
)
data_types <- data_types %>%
arrange(desc(Missing_Percentage))
print(data_types)
## # A tibble: 17 × 6
## Variable Data_Type Non_Missing Missing Missing_Percentage Unique_Values
## <chr> <chr> <int> <int> <dbl> <int>
## 1 plugin_displa… character 28706 253730 89.8 5093
## 2 allowed_tools character 36017 246419 87.2 11273
## 3 enriched_tech… character 127906 154530 54.7 8846
## 4 enriched_topi… character 127906 154530 54.7 767
## 5 description character 282422 14 0.00496 281045
## 6 id character 282436 0 0 282436
## 7 component_id character 282436 0 0 271198
## 8 name character 282436 0 0 282421
## 9 supporting_as… numeric 282436 0 0 21
## 10 plugin_id character 282436 0 0 49930
## 11 plugin_slug character 282436 0 0 49930
## 12 plugin_name character 282436 0 0 43551
## 13 plugin_stars numeric 282436 0 0 1185
## 14 plugin_catego… character 282436 0 0 206
## 15 usage_count numeric 282436 0 0 314
## 16 name_key character 282436 0 0 282421
## 17 variant_count numeric 282436 0 0 193
write_csv(
data_types,
file.path(table_dir, "data_types.csv")
)
missing_data <- data_types %>%
arrange(desc(Missing_Percentage))
print(missing_data)
## # A tibble: 17 × 6
## Variable Data_Type Non_Missing Missing Missing_Percentage Unique_Values
## <chr> <chr> <int> <int> <dbl> <int>
## 1 plugin_displa… character 28706 253730 89.8 5093
## 2 allowed_tools character 36017 246419 87.2 11273
## 3 enriched_tech… character 127906 154530 54.7 8846
## 4 enriched_topi… character 127906 154530 54.7 767
## 5 description character 282422 14 0.00496 281045
## 6 id character 282436 0 0 282436
## 7 component_id character 282436 0 0 271198
## 8 name character 282436 0 0 282421
## 9 supporting_as… numeric 282436 0 0 21
## 10 plugin_id character 282436 0 0 49930
## 11 plugin_slug character 282436 0 0 49930
## 12 plugin_name character 282436 0 0 43551
## 13 plugin_stars numeric 282436 0 0 1185
## 14 plugin_catego… character 282436 0 0 206
## 15 usage_count numeric 282436 0 0 314
## 16 name_key character 282436 0 0 282421
## 17 variant_count numeric 282436 0 0 193
missing_plot <- missing_data %>%
filter(Missing > 0) %>%
ggplot(
aes(
x = reorder(Variable, Missing_Percentage),
y = Missing_Percentage
)
) +
geom_col() +
coord_flip() +
labs(
title = "Missing Data by Variable",
x = "Variable",
y = "Missing Values (%)"
) +
theme_minimal()
print(missing_plot)
ggsave(
file.path(figure_dir, "01_missing_data.png"),
missing_plot,
width = 10,
height = 7,
dpi = 300
)
duplicate_count <- sum(duplicated(skills))
cat("\nDuplicate rows:", duplicate_count, "\n")
##
## Duplicate rows: 0
duplicate_percentage <-
duplicate_count / nrow(skills) * 100
cat(
"Duplicate percentage:",
round(duplicate_percentage, 2),
"%\n"
)
## Duplicate percentage: 0 %
numeric_data <- skills %>%
select(where(is.numeric))
if (ncol(numeric_data) > 0) {
numeric_summary <- numeric_data %>%
summarise(
across(
everything(),
list(
count = ~sum(!is.na(.)),
mean = ~mean(., na.rm = TRUE),
median = ~median(., na.rm = TRUE),
sd = ~sd(., na.rm = TRUE),
variance = ~var(., na.rm = TRUE),
minimum = ~min(., na.rm = TRUE),
maximum = ~max(., na.rm = TRUE),
skewness = ~{
x <- .[!is.na(.)]
if (length(x) > 2)
mean((x - mean(x))^3) /
sd(x)^3
else NA
}
)
)
)
print(numeric_summary)
write_csv(
numeric_summary,
file.path(
table_dir,
"numeric_descriptive_statistics.csv"
)
)
}
## # A tibble: 1 × 32
## supporting_assets_count_count supporting_assets_count…¹ supporting_assets_co…²
## <int> <dbl> <dbl>
## 1 282436 1.86 0
## # ℹ abbreviated names: ¹supporting_assets_count_mean,
## # ²supporting_assets_count_median
## # ℹ 29 more variables: supporting_assets_count_sd <dbl>,
## # supporting_assets_count_variance <dbl>,
## # supporting_assets_count_minimum <dbl>,
## # supporting_assets_count_maximum <dbl>,
## # supporting_assets_count_skewness <dbl>, plugin_stars_count <int>, …
popularity_variables <- names(skills)[
str_detect(
names(skills),
regex(
"star|copy|click|download|install|fork|usage|view",
ignore_case = TRUE
)
)
]
cat("\nPotential popularity variables:\n")
##
## Potential popularity variables:
print(popularity_variables)
## [1] "plugin_stars" "usage_count"
if ("plugin_stars" %in% names(skills)) {
stars_summary <- skills %>%
summarise(
Count = sum(!is.na(plugin_stars)),
Mean = mean(plugin_stars, na.rm = TRUE),
Median = median(plugin_stars, na.rm = TRUE),
SD = sd(plugin_stars, na.rm = TRUE),
Minimum = min(plugin_stars, na.rm = TRUE),
Maximum = max(plugin_stars, na.rm = TRUE)
)
}
print(stars_summary)
## # A tibble: 1 × 6
## Count Mean Median SD Minimum Maximum
## <int> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 282436 634. 2 7110. 0 291990
write_csv(
stars_summary,
file.path(
table_dir,
"stars_summary.csv"
)
)
stars_histogram <- ggplot(
skills,
aes(x = plugin_stars)
) +
geom_histogram(
bins = 50
) +
labs(
title = "Distribution of GitHub Stars",
x = "GitHub Stars",
y = "Number of Skills"
) +
theme_minimal()
print(stars_histogram)
ggsave(
file.path(
figure_dir,
"02_stars_distribution.png"
),
stars_histogram,
width = 10,
height = 6,
dpi = 300
)
stars_log <- skills %>%
filter(plugin_stars >= 0) %>%
mutate(
log_stars = log10(plugin_stars + 1)
)
stars_log_plot <- ggplot(
stars_log,
aes(x = log_stars)
) +
geom_histogram(
bins = 50
) +
labs(
title = "Log-Transformed Distribution of GitHub Stars",
x = "log10(plugin_stars + 1)",
y = "Number of Skills"
) +
theme_minimal()
print(stars_log_plot)
ggsave(
file.path(
figure_dir,
"03_log_stars_distribution.png"
),
stars_log_plot,
width = 10,
height = 6,
dpi = 300
)
if ("plugin_stars" %in% names(skills)) {
top_skills <- skills %>%
arrange(desc(plugin_stars)) %>%
slice_head(n = 20)
print(top_skills)
write_csv(
top_skills,
file.path(
table_dir,
"top_20_skills_by_stars.csv"
)
)
}
## # A tibble: 20 × 17
## id component_id name description allowed_tools supporting_assets_co…¹
## <chr> <chr> <chr> <chr> <chr> <dbl>
## 1 d4b63049… diagnosing-… diag… Investigat… <NA> 19
## 2 2e6e5eb4… implement impl… Implements… <NA> 1
## 3 5e54f489… writing-for… writ… Guides the… <NA> 2
## 4 d291ab4a… wait-what wait… Triggers c… <NA> 1
## 5 e26dedaa… implement-s… impl… Orchestrat… <NA> 1
## 6 29a167cd… pr pr Generates … <NA> 2
## 7 83323e2e… springboot-… spri… Guides Spr… <NA> 0
## 8 de6220c6… regex-vs-ll… rege… Decision f… <NA> 0
## 9 783aa2df… cpp-coding-… cpp-… Enforces C… <NA> 0
## 10 a394cc78… springboot-… spri… Runs a Spr… <NA> 0
## 11 c8f654b3… investor-ma… inve… Creates an… <NA> 0
## 12 ae670291… cpp-testing cpp-… Guides C++… <NA> 0
## 13 a03b061c… quality-non… qual… Guides qua… <NA> 0
## 14 8c4f3160… carrier-rel… carr… Codifies c… <NA> 0
## 15 110f4eb8… customs-tra… cust… Guides cus… <NA> 0
## 16 30e2fe2e… energy-proc… ener… Provides c… <NA> 0
## 17 9f7e3873… inventory-d… inve… Codifies d… <NA> 0
## 18 f3d60e65… logistics-e… logi… Handles fr… <NA> 0
## 19 7b9d88b9… production-… prod… Codifies p… <NA> 0
## 20 be4b8bc8… returns-rev… retu… Codified e… <NA> 0
## # ℹ abbreviated name: ¹supporting_assets_count
## # ℹ 11 more variables: plugin_id <chr>, plugin_slug <chr>, plugin_name <chr>,
## # plugin_display_name <chr>, plugin_stars <dbl>, plugin_categories <chr>,
## # usage_count <dbl>, enriched_technologies <chr>, enriched_topics <chr>,
## # name_key <chr>, variant_count <dbl>
names(skills)
## [1] "id" "component_id"
## [3] "name" "description"
## [5] "allowed_tools" "supporting_assets_count"
## [7] "plugin_id" "plugin_slug"
## [9] "plugin_name" "plugin_display_name"
## [11] "plugin_stars" "plugin_categories"
## [13] "usage_count" "enriched_technologies"
## [15] "enriched_topics" "name_key"
## [17] "variant_count"
if ("enriched_technologies" %in% names(skills)) {
technology_counter <- list()
for (value in skills$enriched_technologies) {
if (is.na(value)) {
next
}
value <- str_trim(as.character(value))
### Skip empty lists
if (
value == "" ||
value == "[]"
) {
next
}
tryCatch({
technologies <- fromJSON(value)
if (is.character(technologies)) {
for (technology in technologies) {
technology <- str_trim(
as.character(technology)
)
if (
technology != "" &&
!is.na(technology)
) {
technology_counter[[length(
technology_counter
) + 1]] <- technology
}
}
}
}, error = function(e) {
### Ignore malformed list values
})
}
technology_counts <- tibble(
Technology = unlist(
technology_counter
)
) %>%
count(
Technology,
sort = TRUE,
name = "Count"
)
print(
technology_counts %>%
slice_head(n = 30)
)
write_csv(
technology_counts,
file.path(
table_dir,
"technology_counts.csv"
)
)
}
## # A tibble: 30 × 2
## Technology Count
## <chr> <int>
## 1 python 7914
## 2 typescript 3635
## 3 git 2673
## 4 github 2337
## 5 javascript 2114
## 6 node 1938
## 7 react 1878
## 8 rest-api 1790
## 9 docker 1748
## 10 css 1615
## # ℹ 20 more rows
technology_plot <- technology_counts %>%
slice_head(n = 30) %>%
ggplot(
aes(
x = Count,
y = reorder(
Technology,
Count
)
)
) +
geom_col() +
labs(
title = "Top 30 Technologies Used by Skills",
x = "Number of Skills",
y = "Technology"
) +
theme_minimal()
print(technology_plot)
ggsave(
file.path(
figure_dir,
"04_top_technologies.png"
),
technology_plot,
width = 10,
height = 7,
dpi = 300
)
if (“category” %in% names(skills)) {
category_counts <- skills %>% filter( !is.na(category), str_trim(as.character(category)) != “” ) %>% count( category, sort = TRUE )
print(category_counts)
write_csv( category_counts, file.path( table_dir, “category_counts.csv” ) )
category_plot <- category_counts %>% slice_head(n = 20) %>% ggplot( aes( x = n, y = reorder(category, n) ) ) + geom_col() + labs( title = “Most Common Skill Categories”, x = “Number of Skills”, y = “Category” ) + theme_minimal()
print(category_plot)
ggsave( file.path( figure_dir, “05_skill_categories.png” ), category_plot, width = 10, height = 7, dpi = 300 ) }
author_column <- names(skills)[ str_detect( names(skills), regex( “author|owner|publisher”, ignore_case = TRUE ) )][1]
if (!is.na(author_column)) {
author_counts <- skills %>% filter( !is.na(.data[[author_column]]), str_trim( as.character(.data[[author_column]]) ) != “” ) %>% count( .data[[author_column]], sort = TRUE, name = “Skills” )
print( author_counts %>% slice_head(n = 20) )
write_csv( author_counts, file.path( table_dir, “author_counts.csv” ) ) }
description_column <- names(skills)[
str_detect(
names(skills),
regex(
"description",
ignore_case = TRUE
)
)
][1]
if (!is.na(description_column)) {
skills <- skills %>%
mutate(
description_length =
str_length(
as.character(
.data[[description_column]]
)
)
)
description_summary <- skills %>%
summarise(
Count = sum(
!is.na(description_length)
),
Mean = mean(
description_length,
na.rm = TRUE
),
Median = median(
description_length,
na.rm = TRUE
),
SD = sd(
description_length,
na.rm = TRUE
),
Minimum = min(
description_length,
na.rm = TRUE
),
Maximum = max(
description_length,
na.rm = TRUE
)
)
print("Description summary")
print(description_summary)
write_csv(
description_summary,
file.path(
table_dir,
"description_length_summary.csv"
)
)
}
## [1] "Description summary"
## # A tibble: 1 × 6
## Count Mean Median SD Minimum Maximum
## <int> <dbl> <dbl> <dbl> <int> <int>
## 1 282422 267. 197 206. 1 16724
description_plot <- ggplot(
skills,
aes(x = description_length)
) +
geom_histogram(
bins = 50
) +
labs(
title = "Distribution of Skill Description Length",
x = "Description Length (characters)",
y = "Number of Skills"
) +
theme_minimal()
print(description_plot)
ggsave(
file.path(
figure_dir,
"06_description_length.png"
),
description_plot,
width = 10,
height = 6,
dpi = 300
)
if (!is.na(description_column)) {
description_words <- skills %>%
select(
description = all_of(
description_column
)
) %>%
filter(
!is.na(description)
) %>%
unnest_tokens(
word,
description
) %>%
anti_join(
stop_words,
by = "word"
) %>%
filter(
str_detect(
word,
"^[a-zA-Z][a-zA-Z0-9+#.-]*$"
)
) %>%
count(
word,
sort = TRUE
)
print(
description_words %>%
slice_head(n = 30)
)
write_csv(
description_words,
file.path(
table_dir,
"description_word_frequency.csv"
)
)
word_plot <- description_words %>%
slice_head(n = 20) %>%
ggplot(
aes(
x = n,
y = reorder(word, n)
)
) +
geom_col() +
labs(
title = "Most Frequent Terms in Skill Descriptions",
x = "Frequency",
y = "Word"
) +
theme_minimal()
print(word_plot)
ggsave(
file.path(
figure_dir,
"07_description_keywords.png"
),
word_plot,
width = 10,
height = 7,
dpi = 300
)
}
## # A tibble: 30 × 2
## word n
## <chr> <int>
## 1 user 56649
## 2 code 36780
## 3 skill 35372
## 4 review 30336
## 5 data 27255
## 6 design 25259
## 7 agent 24266
## 8 project 22302
## 9 und 20821
## 10 de 20815
## # ℹ 20 more rows
numeric_data <- skills %>%
select(where(is.numeric))
if (ncol(numeric_data) >= 2) {
correlation_matrix <- cor(
numeric_data,
use = "pairwise.complete.obs"
)
print(
round(
correlation_matrix,
2
)
)
correlation_long <- as.data.frame(
correlation_matrix
) %>%
rownames_to_column(
"Variable_1"
) %>%
pivot_longer(
-Variable_1,
names_to = "Variable_2",
values_to = "Correlation"
)
write_csv(
correlation_long,
file.path(
table_dir,
"correlation_matrix.csv"
)
)
}
## supporting_assets_count plugin_stars usage_count
## supporting_assets_count 1.00 0.00 -0.03
## plugin_stars 0.00 1.00 0.50
## usage_count -0.03 0.50 1.00
## variant_count 0.00 0.11 0.23
## description_length 0.16 -0.04 -0.06
## variant_count description_length
## supporting_assets_count 0.00 0.16
## plugin_stars 0.11 -0.04
## usage_count 0.23 -0.06
## variant_count 1.00 -0.04
## description_length -0.04 1.00
if ("plugin_stars" %in% names(skills)) {
plugin_stars <- skills %>%
filter(
!is.na(plugin_stars),
plugin_stars >= 0
) %>%
arrange(desc(plugin_stars)) %>%
pull(plugin_stars)
total_stars <- sum(plugin_stars)
top_n_values <- c(
10,
20,
50,
100,
500
)
concentration <- tibble(
Top_N = top_n_values
) %>%
mutate(
Stars = map_dbl(
Top_N,
~sum(
head(
plugin_stars,
min(.x, length(plugin_stars))
)
)
),
Percentage_of_Total =
Stars / total_stars * 100
)
print(concentration)
write_csv(
concentration,
file.path(
table_dir,
"popularity_concentration.csv"
)
)
}
## # A tibble: 5 × 3
## Top_N Stars Percentage_of_Total
## <dbl> <dbl> <dbl>
## 1 10 2708722 1.51
## 2 20 5383902 3.01
## 3 50 13409442 7.49
## 4 100 26785342 15.0
## 5 500 56327139 31.5
concentration_plot <- ggplot(
concentration,
aes(
x = Top_N,
y = Percentage_of_Total
)
) +
geom_line() +
geom_point(size = 3) +
scale_x_continuous(
trans = "log10",
breaks = top_n_values
) +
scale_y_continuous(
labels = function(x) {
paste0(
x,
"%"
)
}
) +
labs(
title = "Concentration of GitHub Stars",
subtitle =
"Share of total stars captured by the top N skills",
x = "Top N Skills (log scale)",
y = "Percentage of Total Stars"
) +
theme_minimal()
print(concentration_plot)
ggsave(
file.path(
figure_dir,
"08_star_concentration.png"
),
concentration_plot,
width = 10,
height = 6,
dpi = 300
)
if ("plugin_stars" %in% names(skills)) {
pareto <- skills %>%
filter(
!is.na(plugin_stars),
plugin_stars >= 0
) %>%
arrange(desc(plugin_stars)) %>%
mutate(
cumulative_stars =
cumsum(plugin_stars),
cumulative_percentage =
cumulative_stars /
sum(plugin_stars) *
100,
percentage_of_skills =
row_number() /
n() *
100
)
thresholds <- c(
50,
75,
80,
90,
95
)
pareto_results <- tibble(
Target_Percentage = thresholds
) %>%
rowwise() %>%
mutate(
Number_of_Skills = which(
pareto$cumulative_percentage >=
Target_Percentage
)[1]
) %>%
ungroup() %>%
mutate(
Percentage_of_Skills =
Number_of_Skills /
nrow(pareto) *
100
)
print(pareto_results)
write_csv(
pareto_results,
file.path(
table_dir,
"pareto_analysis.csv"
)
)
}
## # A tibble: 5 × 3
## Target_Percentage Number_of_Skills Percentage_of_Skills
## <dbl> <int> <dbl>
## 1 50 1207 0.427
## 2 75 2281 0.808
## 3 80 2599 0.920
## 4 90 5501 1.95
## 5 95 12670 4.49
calculate_gini <- function(x) {
x <- x[
!is.na(x) &
x >= 0
]
if (length(x) == 0) {
return(NA_real_)
}
if (sum(x) == 0) {
return(0)
}
x <- sort(x)
n <- length(x)
index <- seq_len(n)
gini <- (
2 * sum(
index * x
) /
(n * sum(x))
-
(n + 1) / n
)
return(gini)
}
if ("plugin_stars" %in% names(skills)) {
gini_stars <- calculate_gini(
skills$plugin_stars
)
cat(
"\nGini coefficient for GitHub stars:",
round(
gini_stars,
4
),
"\n"
)
gini_result <- tibble(
Measure =
"GitHub Stars",
Gini_Coefficient =
gini_stars
)
write_csv(
gini_result,
file.path(
table_dir,
"gini_coefficient.csv"
)
)
}
##
## Gini coefficient for GitHub stars: 0.9797
names(skills)
## [1] "id" "component_id"
## [3] "name" "description"
## [5] "allowed_tools" "supporting_assets_count"
## [7] "plugin_id" "plugin_slug"
## [9] "plugin_name" "plugin_display_name"
## [11] "plugin_stars" "plugin_categories"
## [13] "usage_count" "enriched_technologies"
## [15] "enriched_topics" "name_key"
## [17] "variant_count" "description_length"
cat("\n")
cat("====================================================\n")
## ====================================================
cat("KEY FINDINGS FOR PRESENTATION\n")
## KEY FINDINGS FOR PRESENTATION
cat("====================================================\n")
## ====================================================
cat(
"\n1. DATASET SIZE\n"
)
##
## 1. DATASET SIZE
cat(
"The dataset contains",
format(
nrow(skills),
big.mark = ","
),
"skills across",
ncol(skills),
"variables.\n"
)
## The dataset contains 282,436 skills across 18 variables.
if ("plugin_stars" %in% names(skills)) {
cat(
"\n2. POPULARITY\n"
)
cat(
"Total GitHub stars:",
format(
sum(
skills$plugin_stars,
na.rm = TRUE
),
big.mark = ","
),
"\n"
)
cat(
"Median GitHub stars:",
format(
median(
skills$plugin_stars,
na.rm = TRUE
),
big.mark = ","
),
"\n"
)
cat(
"\n3. POPULARITY CONCENTRATION\n"
)
top_500 <- min(
500,
length(
skills$plugin_stars[
!is.na(skills$plugin_stars)
]
)
)
sorted_stars <- sort(
skills$plugin_stars[
!is.na(skills$plugin_stars)
],
decreasing = TRUE
)
concentration_500 <-
sum(
head(
sorted_stars,
top_500
)
) /
sum(
sorted_stars
) *
100
cat(
"Top",
top_500,
"skills account for",
round(
concentration_500,
2
),
"% of total GitHub stars.\n"
)
cat(
"\n4. INEQUALITY\n"
)
cat(
"Gini coefficient:",
round(
gini_stars,
4
),
"\n"
)
}
##
## 2. POPULARITY
## Total GitHub stars: 179,001,899
## Median GitHub stars: 2
##
## 3. POPULARITY CONCENTRATION
## Top 500 skills account for 31.47 % of total GitHub stars.
##
## 4. INEQUALITY
## Gini coefficient: 0.9797
cat("\n====================================================\n")
##
## ====================================================
cat("ANALYSIS COMPLETE\n")
## ANALYSIS COMPLETE
cat("====================================================\n")
## ====================================================
cat(
"\nTables saved to:",
table_dir,
"\n"
)
##
## Tables saved to: output/tables
cat(
"Figures saved to:",
figure_dir,
"\n"
)
## Figures saved to: output/figures