Search code examples
pythonpandasdiscord

How do I turn a Pandas DataFrame into a Discord Embed?


I am currently working on a Discord Bot that takes Data from a Google Spreadsheet and converts it into a Pandas DataFrame. Using said DataFrame the Bot then outputs Particular Data a User asks for. The Spreadsheet looks like this: Name | Clan | Country | Notes (those are the columns, in the rows are the respective Infomations for about 1000 Players of a game). I created a few different DataFrames based on the complete one:

# Fields
fields_with_clan = ['Name', 'Clan']
fields_just_name = ['Name']
fields_with_country = ['Name', 'Country']
fields_fullinfo = ['Name', 'Clan', 'Country']
fields_countries_only = ['Country']

# Respective DataFrames for each field
df = pd.read_csv(f"https://docs.google.com/spreadsheets/d/{sheet_id}/export?format=csv")
df_players_clans = pd.read_csv(f"https://docs.google.com/spreadsheets/d/{sheet_id}/export?format=csv",
                               usecols=fields_with_clan)
df_players = pd.read_csv(f"https://docs.google.com/spreadsheets/d/{sheet_id}/export?format=csv",
                         usecols=fields_just_name)
df_players_countries = pd.read_csv(f"https://docs.google.com/spreadsheets/d/{sheet_id}/export?format=csv",
                                   usecols=fields_with_country)
df_players_fullinfo = pd.read_csv(f"https://docs.google.com/spreadsheets/d/{sheet_id}/export?format=csv",
                                  usecols=fields_fullinfo)
df_countries_only = pd.read_csv(f"https://docs.google.com/spreadsheets/d/{sheet_id}/export?format=csv",
                                usecols=fields_countries_only)

I also created a Dictionary that translates the common spelling (Abbreviations) of a clan to the complete name used in the Spreadsheet:

Dict_Clans = {'zt': 'Zero Tolerance - ƵŦ✿', 'kaveh': 'Kaveh - :K', 'dw': 'Deadly Warriors - Ðฬ',
              'nf': 'Next Force - NF', ... }

Now, one function of the bot is to output every Member of a Clan, using this code:

# List all members of given clan
@client.command(name='members')
async def members(context, *, index: str):
    if df_players[df_players_clans.values == [Dict_Clans.get(index)]].empty != True:
        await context.message.channel.send(df_players[df_players_clans.values == [Dict_Clans.get(index)]])
    else:
        await context.message.channel.send("Unfortunately, we don't have '" + index + "' in our Database.")

This works; e.g. if the user types "?members zt" the Bot outputs a DataFrame containing all Players that are part of ZT clan. The problem is, it doesn't look too pretty on Discord. I would like the DataFrame to be output as a Discord Embed with its titles being the Name of each Player. I was thinking the smartest way might be a while function, but I can't seem to implement it properly.

Thanks in advance for your Answers.


Solution

  • Kinda late but hope this helps.

    pip install bokeh

    Download geckodriver & chormedriver and add their paths to your Environment Variables

    Then try converting the dataframe to a png.

    from bokeh.io import export_png, export_svgs
    from bokeh.models import ColumnDataSource, DataTable, TableColumn
    
    def load_from_gspreadsheet(sheet_name, key):
        url = 'https://docs.google.com/spreadsheets/d/{key}/gviz/tq?tqx=out:csv&sheet={sheet_name}&headers=1'.format(
            key=key, sheet_name=sheet_name.replace(' ', '%20'))
    
    
    def save_df_as_image(df, path):
        source = ColumnDataSource(df)
        df_columns = [df.index.name]
        df_columns.extend(df.columns.values)
        columns_for_table=[]
        print(df_columns)
        for column in df_columns:
            if column != None:
                columns_for_table.append(TableColumn(field=column, title=column))
    
        data_table = DataTable(source=source, columns=columns_for_table,height_policy="auto",width_policy="auto",index_position=None)
        export_png(data_table, filename = path)
    
    
    @bot.command()
    async def fetch(ctx):
           df = load_from_gspreadsheet(sheet_name, spreadsheet_id)
           pt = os.getcwd()
           save_df_as_image(df, os.path.join(pt,'plot.png'))
           file=discord.File('plot.png')
           e = discord.Embed()
           e.set_image(url="attachment://plot.png")
           # await ctx.send(file=discord.File('plot.png'))
           await ctx.send(file = file, embed = e)```