import gradio as gr import pandas as pd import numpy as np import plotly.express as px from datasets import load_dataset def load_transform_data(): """ Load and transform data from a parquet file. Returns: pandas.DataFrame: Transformed dataframe. """ spaces_dataset = "jsulz/space-stats" dataset = load_dataset(spaces_dataset) df = dataset["train"].to_pandas() # combine the sdk and tags columns, one of which is a string and the other is an array of strings df["sdk"] = df["sdk"].apply(lambda x: np.array([str(x)])) df["licenses"] = df["license"].apply( lambda x: np.array([str(x)]) if x is None else x ) # then combine the sdk and tags columns so that their elements are together df["sdk_tags"] = df[["sdk", "tags"]].apply( lambda x: np.concatenate((x.iloc[0], x.iloc[1])), axis=1 ) # Fill the NaN values with an empty string df["emoji"] = np.where(df["emoji"].isnull(), "", df["emoji"]) # where the custom_domains column is not null, use that as the url, otherwise, use the host column df["url"] = np.where( df["custom_domains"].isnull(), df["id"], df["custom_domains"], ) # Build up a pretty url that's clickable with the emoji df["url"] = df[["url", "emoji"]].apply( lambda x: ( f'{str(x.iloc[1]) + " " + x.iloc[0]}' if x.iloc[0] is not None else f'{str(x.iloc[1]) + " " + x.iloc[0][0]}' ), axis=1, ) # Prep the models, datasets, and licenses columns for display df["r_models"] = [ ", ".join(models) if models is not None else "" for models in df["models"] ] df["r_sdk_tags"] = [ ", ".join(sdk_tags) if sdk_tags is not None else "" for sdk_tags in df["sdk_tags"] ] df["r_datasets"] = [ ", ".join(datasets) if datasets is not None else "" for datasets in df["datasets"] ] df["r_licenses"] = [ ", ".join(licenses) if licenses is not None else "" for licenses in df["licenses"] ] return df def filtered_df( filtered_emojis, filtered_likes, filtered_author, filtered_hardware, filtered_tags, filtered_models, filtered_datasets, space_licenses, filtered_devmode, ): """ Filter the dataframe based on the given criteria. Args: filtered_emojis (list): List of emojis to filter the dataframe by. filtered_likes (int): Minimum number of likes to filter the dataframe by. filtered_author (list): List of authors to filter the dataframe by. filtered_hardware (list): List of hardware to filter the dataframe by. filtered_tags (list): List of tags to filter the dataframe by. filtered_models (list): List of models to filter the dataframe by. filtered_datasets (list): List of datasets to filter the dataframe by. space_licenses (list): List of licenses to filter the dataframe by. Returns: pandas.DataFrame: Filtered dataframe with the following columns: "URL", "Likes", "Models", "Datasets", "Licenses". """ _df = df if filtered_emojis: _df = _df[_df["emoji"].isin(filtered_emojis)] if filtered_likes: _df = _df[_df["likes"] >= filtered_likes] if filtered_author: _df = _df[_df["author"].isin(filtered_author)] if filtered_hardware: _df = _df[_df["hardware"].isin(filtered_hardware)] if filtered_tags: _df = _df[ _df["sdk_tags"].apply(lambda x: any(tag in x for tag in filtered_tags)) ] if filtered_models: _df = _df[ _df["models"].apply( lambda x: ( any(model in x for model in filtered_models) if x is not None else False ) ) ] if filtered_datasets: _df = _df[ _df["datasets"].apply( lambda x: ( any(dataset in x for dataset in filtered_datasets) if x is not None else False ) ) ] if space_licenses: _df = _df[ _df["licenses"].apply( lambda x: ( any(space_license in x for space_license in space_licenses) if x is not None else False ) ) ] # rename the columns names to make them more readable _df = _df.rename( columns={ "url": "URL", "likes": "Likes", "r_models": "Models", "r_datasets": "Datasets", "r_licenses": "Licenses", } ) if filtered_devmode: _df = _df[_df["devMode"] == filtered_devmode] return _df[["URL", "Likes", "Models", "Datasets", "Licenses"]] def count_items(items): """ Count the occurrences of items and authors in a given list of items. Parameters: items (dataframe column): A dataframe column containing a list of items. Returns: tuple: A tuple containing two dictionaries. The first dictionary contains the count of each item, and the second dictionary contains the count of each author. """ items = np.concatenate([arr for arr in items.values if arr is not None]) item_count = {} item_author_count = {} for item in items: if item in item_count: item_count[item] += 1 else: item_count[item] = 1 author = item.split("/")[0] if author in item_author_count: item_author_count[author] += 1 else: item_author_count[author] = 1 return item_count, item_author_count def flatten_column(_df, column): """ Flattens a column in a DataFrame. Args: _df (pandas.DataFrame): The DataFrame containing the column. column (str): The name of the column to flatten. Returns: list: A list of unique values from the flattened column. """ column_to_list = _df[column].apply( lambda x: np.array(["None"]) if np.ndim(x) == 0 else x ) flattened = np.concatenate(column_to_list.values) uniques = np.unique(flattened) return uniques.tolist() with gr.Blocks(fill_width=True) as demo: df = load_transform_data() with gr.Tab(label="Spaces Overview"): with gr.Row(): # Create a pie charge showing the distribution of spaces by SDK fig2 = px.pie( df, names="sdk", title="Distribution of Spaces by SDK", template="plotly_dark", ) gr.Plot(fig2) # create a pie chart showing the distribution of spaces by emoji for the top 10 used emojis emoji_counts = df["emoji"].value_counts().head(10).reset_index() fig3 = px.pie( emoji_counts, names="emoji", values="count", title="Distribution of Spaces by Emoji", template="plotly_dark", ) gr.Plot(fig3) # Create a scatter plot showing the relationship between the number of likes and the number of spaces created by an author author_likes = ( df.groupby("author").agg({"likes": "sum", "id": "count"}).reset_index() ) fig4 = px.scatter( author_likes, x="id", y="likes", title="Relationship between Number of Spaces Created and Number of Likes", labels={"id": "Number of Spaces Created", "likes": "Number of Likes"}, hover_data={"author": True}, template="plotly_dark", ) gr.Plot(fig4) # Create a scatter plot showing the relationship between the number of likes and the number of spaces created by an author emoji_likes = ( df.groupby("emoji") .agg({"likes": "sum", "id": "count"}) .sort_values(by="likes", ascending=False) .head(20) .reset_index() ) fig10 = px.scatter( emoji_likes, x="id", y="likes", title="Relationship between Space Emoji and Number of Likes", labels={"id": "Number of Spaces Created", "likes": "Number of Likes"}, hover_data={"emoji": True}, template="plotly_dark", ) gr.Plot(fig10) # Create a bar chart of hardware in use hardware = df["hardware"].value_counts().reset_index() hardware.columns = ["Hardware", "Number of Spaces"] fig5 = px.bar( hardware, x="Hardware", y="Number of Spaces", title="Hardware in Use", labels={ "Hardware": "Hardware", "Number of Spaces": "Number of Spaces (log scale)", }, color="Hardware", template="plotly_dark", ) fig5.update_layout(yaxis_type="log") gr.Plot(fig5) model_count, model_author_count = count_items(df["models"]) model_author_count = pd.DataFrame( model_author_count.items(), columns=["Model Author", "Number of Spaces"] ) fig8 = px.bar( model_author_count.sort_values("Number of Spaces", ascending=False).head( 20 ), x="Model Author", y="Number of Spaces", title="Most Popular Model Authors", labels={"Model": "Model", "Number of Spaces": "Number of Spaces"}, template="plotly_dark", ) gr.Plot(fig8) model_count = pd.DataFrame( model_count.items(), columns=["Model", "Number of Spaces"] ) # then make a bar chart fig6 = px.bar( model_count.sort_values("Number of Spaces", ascending=False).head(20), x="Model", y="Number of Spaces", title="Most Used Models", labels={"Model": "Model", "Number of Spaces": "Number of Spaces"}, template="plotly_dark", ) gr.Plot(fig6) dataset_count, dataset_author_count = count_items(df["datasets"]) dataset_count = pd.DataFrame( dataset_count.items(), columns=["Datasets", "Number of Spaces"] ) dataset_author_count = pd.DataFrame( dataset_author_count.items(), columns=["Dataset Author", "Number of Spaces"] ) fig9 = px.bar( dataset_author_count.sort_values("Number of Spaces", ascending=False).head( 20 ), x="Dataset Author", y="Number of Spaces", title="Most Popular Dataset Authors", labels={ "Dataset Author": "Dataset Author", "Number of Spaces": "Number of Spaces", }, template="plotly_dark", ) gr.Plot(fig9) # then make a bar chart fig7 = px.bar( dataset_count.sort_values("Number of Spaces", ascending=False).head(20), x="Datasets", y="Number of Spaces", title="Most Used Datasets", labels={"Datasets": "Datasets", "Number of Spaces": "Number of Spaces"}, template="plotly_dark", ) gr.Plot(fig7) with gr.Row(): # Get the most duplicated spaces duplicated_spaces = ( df["duplicated_from"].value_counts().head(20).reset_index() ) duplicated_spaces["duplicated_from"] = duplicated_spaces[ "duplicated_from" ].apply( lambda x: f"{x}" ) duplicated_spaces.columns = ["Space", "Number of Duplicates"] gr.DataFrame(duplicated_spaces, datatype="html") # Get the most liked spaces liked_spaces = ( df[["id", "likes"]].sort_values(by="likes", ascending=False).head(20) ) liked_spaces["id"] = liked_spaces["id"].apply( lambda x: f"{x}" ) liked_spaces.columns = ["Space", "Number of Likes"] gr.DataFrame(liked_spaces, datatype="html") with gr.Row(): # Create a dataframe with the top 10 authors and the number of spaces they have created author_counts = df["author"].value_counts().head(20).reset_index() author_counts["author"] = author_counts["author"].apply( lambda x: f"{x}" ) author_counts.columns = ["Author", "Number of Spaces"] gr.DataFrame(author_counts, datatype="html") # create a dataframe where we groupby author and sum their likes author_likes = df.groupby("author").agg({"likes": "sum"}).reset_index() author_likes = author_likes.sort_values(by="likes", ascending=False).head( 20 ) author_likes["author"] = author_likes["author"].apply( lambda x: f"{x}" ) author_likes.columns = ["Author", "Number of Likes"] gr.DataFrame(author_likes, datatype="html") with gr.Tab(label="Spaces Search"): df = df[df["stage"] == "RUNNING"] # Layout with gr.Row(): emoji = gr.Dropdown( df["emoji"].unique().tolist(), label="Search by Emoji 🤗", multiselect=True, ) # Dropdown to select the emoji likes = gr.Slider( minimum=df["likes"].min(), maximum=df["likes"].max(), step=1, label="Filter by Likes", ) # Slider to filter by likes with gr.Row(): author = gr.Dropdown( df["author"].unique().tolist(), label="Search by Author", multiselect=True, ) # get the list of unique strings in the sdk_tags column sdk_tags = np.unique(np.concatenate(df["sdk_tags"].values)) # create a dropdown for the sdk_tags sdk_tags = gr.Dropdown( sdk_tags.tolist(), label="Filter by SDK/Tags", multiselect=True ) with gr.Row(): # create a gradio checkbox group for hardware hardware = gr.CheckboxGroup( df["hardware"].unique().tolist(), label="Filter by Hardware" ) licenses = np.unique(np.concatenate(df["licenses"].values)) space_license = gr.Dropdown(licenses.tolist(), label="Filter by license") with gr.Row(): models = gr.Dropdown( flatten_column(df, "models"), label="Search by Model", multiselect=True, ) datasets = gr.Dropdown( flatten_column(df, "datasets"), label="Search by Dataset", multiselect=True, ) devmode = gr.Checkbox(label="Show Dev Mode Spaces") clear = gr.ClearButton( components=[ emoji, author, hardware, sdk_tags, models, datasets, space_license, ] ) df = pd.DataFrame( df[ [ "id", "emoji", "author", "url", "likes", "hardware", "sdk_tags", "models", "datasets", "licenses", "r_sdk_tags", "r_models", "r_datasets", "r_licenses", "devMode", ] ] ) gr.DataFrame( filtered_df, inputs=[ emoji, likes, author, hardware, sdk_tags, models, datasets, space_license, devmode, ], datatype="html", wrap=True, column_widths=["25%", "5%", "25%", "25%", "20%"], ) demo.launch(share=True)