Full text
FindingsInstructions.md 2025-10-10 1 / 19 Figure 2 Instructions The following code cells is to create Figure 2, which visualizes the quality assessment scores of the studies included in the systematic literature review (SLR). The figure will display a bar plot of the quality scores, with colors indicating different clusters of quality levels. Before running the code, download the Excel file named Articles_Zenodo.xlsx from the Zenodo repository associated with the literature review. Ensure that this file is in the same directory as your Jupyter notebook or provide the correct path to the file in the code. import pandas as pd from sklearn.cluster import KMeans import numpy as np import matplotlib.pyplot as plt # Load the Excel file excel_file_path = 'Articles_Zenodo.xlsx' # Assuming the file is in the same directory df_excel = pd.read_excel(excel_file_path, sheet_name = 'Study Quality') # Create the 'Study' column by combining 'Authors' and 'Publication Year' df_excel['Study'] = '(' + df_excel['Authors'].astype(str) + ' ' + df_excel['Publication Year'].astype(str) + ')' # Create the new DataFrame 'df_quality' with 'Study' and 'Total' (renamed to 'Score') df_quality = df_excel[['Study', 'Total']].copy() df_quality.rename(columns={'Total': 'Score'}, inplace=True) # Filter studies with quality score >= 3.5 df_quality = df_quality[df_quality['Score'] >= 3.5] # Display the first few rows of the new DataFrame print(df_quality.head()) # Update the data variable to be used by subsequent cells # This ensures that the 'data' variable reflects the structure data = list(df_quality.itertuples(index=False, name=None)) We calculated the inertia for a range of k values and plotted the elbow curve. This helps in determining the optimal number of clusters for K-Means clustering. # Calculate inertia for a range of k values inertia = [] k_range = range(1, 11) # Test k from 1 to 10 # Reshape the 'Score' data for KMeans # KMeans expects a 2D array, so if 'Score' is a single feature, reshape it. X = df_quality[['Score']]
FindingsInstructions.md 2025-10-10 2 / 19 for k in k_range: kmeans_elbow = KMeans(n_clusters=k, random_state=42, n_init='auto') kmeans_elbow.fit(X) inertia.append(kmeans_elbow.inertia_) # Plot the elbow curve plt.figure(figsize=(10, 6)) plt.plot(k_range, inertia, marker='o', linestyle='-') plt.xlabel('Number of Clusters (k)', fontsize=12) plt.ylabel('Inertia (Sum of squared distances)', fontsize=12) plt.title('Elbow Method for Optimal k', fontsize=14) plt.xticks(k_range) plt.grid(True) plt.tight_layout() # Save the plot # Ensure the "Images" directory exists (it should from CELL INDEX 0) plt.savefig("Images/kmeans_elbow_curve.png") # Show the plot plt.show() Ensure that the directory Images exists in your working directory. If it does not exist, create it to save the generated plots. # Perform K-Means clustering # You can adjust the number of clusters (n_clusters) as needed n_clusters = 3 # Example: 3 clusters (e.g., High, Medium, Low quality) kmeans = KMeans(n_clusters=n_clusters, random_state=42, n_init='auto') df_quality['Cluster'] = kmeans.fit_predict(df_quality[['Score']]) # Create a color map for clusters # You can extend this if you have more than 3 clusters cluster_colors = ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd'] # Add more colors if needed df_quality['Cluster_Color'] = df_quality['Cluster'].apply(lambda x: cluster_colors[x % len(cluster_colors)]) # Sort by score for better visualization, if desired df_quality = df_quality.sort_values('Score', ascending=False) # Create the bar plot plt.figure(figsize=(19, 6)) bars = plt.bar(df_quality['Study'], df_quality['Score'], color=df_quality['Cluster_Color']) # Add labels and title # plt.xlabel('Study', fontsize=16) plt.ylabel('Assessment Score', fontsize=18) # plt.title(f'K-Means Clustering of Study Quality Scores (k={n_clusters})',
FindingsInstructions.md 2025-10-10 3 / 19 fontsize=16) plt.xticks(rotation=45, ha="right", fontsize=18) plt.yticks(fontsize=18) plt.ylim(0, 7) # Adjust y-limit for better spacing # Add a horizontal line at y=3.5 (50% of max score 7) plt.axhline(y=3.5, color='red', linestyle='-', linewidth=1.5) # Adjust x-axis limits to remove whitespace plt.xlim([-0.5, df_quality.shape[0] - 0.5]) # Adjust the limits # Create a legend for clusters legend_handles = [] plt.tight_layout() # Save the plot # Ensure the "Images" directory exists (it should from CELL INDEX 0) plt.savefig("Images/quality_assessment_clusters.png") # Show the plot plt.show() print(df_quality[['Study', 'Score', 'Cluster']]) Figure 3 Instructions The Figure 3 presents a VOSviewer co-authorship network. Node size represents the number of publications per author, edges indicate collaborations, and colors distinguish collaborative clusters. Only authors with at least two papers and a non-zero total link strength are displayed. To create this figure, you will need to use VOSviewer software. Follow these steps: 1. Prepare the Data: Download the bibliographic data from the Zenodo repository (RIS format). 2. Open VOSviewer: Launch the VOSviewer application on your computer.
FindingsInstructions.md 2025-10-10 4 / 19 3. Create a New Map: Select Create in the Map section and choose the file you exported in step 1.
FindingsInstructions.md 2025-10-10 5 / 19 4. Select Co-authorship Analysis: Choose "Co-authorship" as the type of analysis you want to perform. 5. Set Thresholds: Set the minimum number of documents per author to 2 and ensure that authors with a total link strength of 0 are excluded.
FindingsInstructions.md 2025-10-10 6 / 19 6. Visualize the Network: Click on "Finish" to create the map and select No when asked to remove not connected nodes to each other. Then use the visualization options to explore the co-authorship network. Figure 4 Instructions Ensure that the directory Images exists in your working directory. If it does not exist, create it to save the generated plots. This code creates the bar plot showing the number of studies per country which represents the country of each author affiliation, colored by continent. import pandas as pd import seaborn as sns import matplotlib.pyplot as plt import matplotlib.ticker as mticker
FindingsInstructions.md 2025-10-10 7 / 19 # Load the Excel file excel_file_path = 'Articles_Zenodo.xlsx' df_countries = pd.read_excel(excel_file_path, sheet_name='Authors') # Explode the 'Author Affiliation' Country' column to handle multiple countries df_countries['Author Affiliation\' Country'] = df_countries['Author Affiliation\' Country'].str.split(';') df_countries_exploded = df_countries.explode('Author Affiliation\' Country') # Strip any leading/trailing whitespace from countries df_countries_exploded['Author Affiliation\' Country'] = df_countries_exploded['Author Affiliation\' Country'].str.strip() # Group by 'Bib entry' and 'Author Affiliation\' Country' and count unique studies per country country_counts = df_countries_exploded.groupby('Author Affiliation\' Country') ['Bib entry'].nunique().sort_values(ascending=False) # Create a mapping of country to continent country_to_continent = df_countries_exploded.groupby('Author Affiliation\' Country')['Author Affiliation\' Continent'].apply(lambda x: x.iloc[0].split(';') [0].strip()).to_dict() # Correct the continent for Australia and New Zealand if 'Australia' in country_to_continent: country_to_continent['Australia'] = 'Oceania' if 'New Zealand' in country_to_continent: # Add New Zealand if it might appear country_to_continent['New Zealand'] = 'Oceania' # Map continents to countries continents = [country_to_continent[country] for country in country_counts.index] # Define a color palette for continents continent_colors = { 'Europe': '#1f77b4', # blue 'North America': '#ff7f0e', # orange 'Asia': '#2ca02c', # green 'Oceania': '#d62728', # red 'Africa': '#9467bd', # purple 'South America': '#8c564b' # brown } # Map colors to the bars based on continent bar_colors = [continent_colors[continent] for continent in continents] # Create the bar plot plt.figure(figsize=(12, 4)) bars = plt.bar(country_counts.index, country_counts.values, color=bar_colors) plt.xticks(rotation=45, ha='right', fontsize=12) plt.yticks(fontsize=12) plt.ylabel('Number of Studies', fontsize=14) # Use a FuncFormatter to format y-axis labels as integers
FindingsInstructions.md 2025-10-10 8 / 19 formatter = mticker.FuncFormatter(lambda x, pos: f'{int(x)}') plt.gca().yaxis.set_major_formatter(formatter) # Count continent occurrences continent_counts = {} for country, count in country_counts.items(): continent = country_to_continent.get(country, 'Unknown') if continent in continent_counts: continent_counts[continent] += count else: continent_counts[continent] = count # Sort continents by occurrence sorted_continents = sorted(continent_counts.items(), key=lambda x: x[1], reverse=True) # Create legend handles and labels handles = [plt.Rectangle((0, 0), 1, 1, color=continent_colors[continent]) for continent, count in sorted_continents] labels = [f"{continent} (n={count})" for continent, count in sorted_continents] # Add legend for continents plt.legend(handles, labels, title='Continent', fontsize=12, title_fontsize=12) plt.tight_layout() # Save the plot plt.savefig("Images/countries_barplot.png") # Show the plot plt.show() country_counts Figure 5 Instructions Figure 5 illustrates the distribution of studies based on the source of the employed LM (closed-source vs. open-source), the primary training method (ICL vs. Fine-tuning), and the model size (SLM vs. LLM). The quadrant in which a study is positioned is the key indicator, while the precise location within the quadrant is not important. Create a folder in the root directory named Plots to save class below. import numpy as np from matplotlib.path import Path import matplotlib.pyplot as plt import matplotlib.patches as patches from matplotlib.collections import PathCollection class QuadrantPlot:
FindingsInstructions.md 2025-10-10 9 / 19 def __init__(self, n_rows=2, n_cols=2, figsize=(10, 8), xquadrant_len=10, yquadrant_len=10): """Initialize a quadrant plot with basic settings. Args: n_rows: Number of rows in the grid (default 2) n_cols: Number of columns in the grid (default 2) xlim: Tuple of (min, max) values for x-axis ylim: Tuple of (min, max) values for y-axis """ self.fig = plt.figure(figsize=figsize) self.ax = plt.subplot(111) self.xlim = (0, xquadrant_len*n_cols) self.ylim = (0, yquadrant_len*n_rows) # print(self.xlim, self.ylim) self.n_rows = n_rows self.n_cols = n_cols self.n_quadrants = n_rows * n_cols # Default colors with repeating pattern if needed base_colors = ['blue', 'green', 'red', 'purple', 'orange', 'cyan', 'magenta', 'yellow', 'brown'] self.colors = (base_colors * (self.n_quadrants // len(base_colors) + 1)) [:self.n_quadrants] # Create empty lists for each quadrant self.dots = [[] for _ in range(self.n_quadrants)] # Set up basic grid structure self._setup_grid() self.ax.set_xlim(self.xlim) self.ax.set_ylim(self.ylim) def _setup_grid(self): """Create grid lines to divide the space into quadrants.""" # Calculate the division points for x and y axes x_divs = np.linspace(self.xlim[0], self.xlim[1], self.n_cols + 1) y_divs = np.linspace(self.ylim[0], self.ylim[1], self.n_rows + 1) """ For example: If self.n_rows = 3, the y-axis will be divided into 3 intervals, requiring 4 points (e.g., [ymin, y1, y2, ymax]). That's why self.n_rows + 1. """ # Draw horizontal lines for y in y_divs[1:-1]: # Skip first and last to avoid drawing on the edges self.ax.axhline(y=y, color='black', linestyle='-', alpha=0.7) # Draw vertical lines for x in x_divs[1:-1]: # Skip first and last to avoid drawing on the edges self.ax.axvline(x=x, color='black', linestyle='-', alpha=0.7)
FindingsInstructions.md 2025-10-10 16 / 19 For Figure 6 that shows the ordered bar plot of model usage distribution in the literature review: # Graph 1: Bar Plot - Model Usage Distribution (Ordered) import matplotlib.pyplot as plt import pandas as pd from matplotlib import colors as mcolors # Prepare data - flatten all models with their usage and producer info all_data = [] for producer in producers: if producer == 'Others': continue for i, model_info in enumerate(models[producer]): model_name, is_closed_source = model_info if isinstance(producer_usage[producer], list): model_usage = producer_usage[producer][i] else: model_usage = producer_usage[producer] all_data.append({ 'producer': producer, 'model': model_name, 'usage': model_usage, 'is_closed_source': is_closed_source }) # Sort by usage (descending order) all_data.sort(key=lambda x: x['usage'], reverse=True) # Create color palette base_colors = ["#0b3f9b", "#4aa60e", "#d31a0d", "#22bbd6", "#e8970b"] producer_color_map = {producer: base_colors[i] for i, producer in enumerate(producers)} # Extract data for plotting model_names = [item['model'] for item in all_data] model_usage = [item['usage'] for item in all_data] bar_colors = [producer_color_map[item['producer']] for item in all_data] # Create bar plot fig, ax = plt.subplots(figsize=(15, 8)) bars = ax.bar(range(len(model_names)), model_usage, color=bar_colors, edgecolor='black') # Add usage labels on top of bars for i, (bar, usage) in enumerate(zip(bars, model_usage)): ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.1, str(usage), ha='center', va='bottom', fontsize=14) # Customize plot ax.set_ylabel('Usage Count', fontsize=14, weight='bold') ax.set_xticks(range(len(model_names))) ax.set_xticklabels(model_names, rotation=45, ha='right', fontsize=18) ax.set_yticks([])
FindingsInstructions.md 2025-10-10 17 / 19 # Make open-source model labels bold for i, label in enumerate(ax.get_xticklabels()): if not all_data[i]['is_closed_source']: label.set_fontweight('bold') legend_elements = [] for i, producer in enumerate(producers): if producer == 'Others': continue legend_elements.append(plt.Rectangle((0, 0), 1, 1, facecolor=base_colors[i], label=producer)) ax.legend(handles=legend_elements, loc='upper right', fontsize=16) plt.tight_layout() plt.savefig('model_usage_distribution.pdf', bbox_inches='tight', dpi=300) plt.show() For Figure 7 that shows the pie chart of usage distribution by producer: # Graph 2: Pie Chart - Usage Distribution by Producer import matplotlib.pyplot as plt # Calculate total usage per producer producer_totals = {} for producer in producers: producer_totals[producer] = sum(producer_usage[producer]) # Create pie chart fig, ax = plt.subplots(figsize=(7, 7)) colors = ["#0b3f9b", "#4aa60e", "#d31a0d", "#22bbd6", "#e8970b"] wedges, texts, autotexts = ax.pie(producer_totals.values(), labels=producer_totals.keys(), autopct='%1.1f%%', colors=colors, startangle=90, textprops={'fontsize': 12}) # Enhance the appearance for autotext in autotexts: autotext.set_fontweight('bold') autotext.set_color('white') [text.set_fontweight('bold') for text in texts] plt.tight_layout() plt.savefig('producer_usage_distribution.pdf', bbox_inches='tight', dpi=300) plt.show() # Print summary statistics
FindingsInstructions.md 2025-10-10 18 / 19 print("Producer Usage Summary:") total_usage = sum(producer_totals.values()) for producer, usage_count in producer_totals.items(): percentage = (usage_count / total_usage) * 100 print(f"{producer}: {usage_count} ({percentage:.1f}%)") Figure 8 Instructions Ensure that the directory Images exists in your working directory. If it does not exist, create it to save the generated plots. For this one, you need to download the multiTimeline.csv file which was obtained from Google Trends. import pandas as pd import matplotlib.pyplot as plt import matplotlib.dates as mdates # Load the dataset df_timeline = pd.read_csv('multiTimeline.csv', skiprows=1) # Skip the header row which might be problematic df_timeline.columns = ['Date', 'Popularity'] # Rename columns for clarity # Convert 'Date' column to datetime objects df_timeline['Date'] = pd.to_datetime(df_timeline['Date']) # Create the plot plt.figure(figsize=(8, 4)) plt.plot(df_timeline['Date'], df_timeline['Popularity'], marker='o', linestyle='- ') # Format the x-axis to show years and months plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m')) plt.gca().xaxis.set_major_locator(mdates.MonthLocator(interval=4)) # Show a tick every 6 months plt.gcf().autofmt_xdate() # Auto-format the x-axis labels to fit # Add labels and title # plt.xlabel('Time Period', fontsize=12) plt.ylabel('Google Trends\' Interest over time', fontsize=12) plt.xticks(fontsize=12) plt.yticks(fontsize=12) plt.ylim(0, 100) # plt.title('Popularity Evolution Over Time') plt.grid(True) plt.tight_layout() # Save the plot plt.savefig("Images/popularity_evolution.png")
FindingsInstructions.md 2025-10-10 19 / 19 # Show the plot plt.show()