Export a table listing all characters and their data

    Output is a CSV file and an Excel file, saved as 'characters.csv/.xlsx' in the output directory.

def character_summary_table():
    """Export a table listing all characters and their data

    Output is a CSV file and an Excel file, saved as 'characters.csv/.xlsx' in the output directory.
    """
    # a database client/session to run queries in
    cl = client.get_client()
    session = cl.create_session()

    # Define the query. Note that we need to rename the two joined-in name columns,
    # to make the labels intelligible and to not have two identical column names in the output.
    # Also, we need a left outer join on the place of birth (instead of the default left inner join)
    # if we want results for characters that have no place of birth set.
    query = session.query(models.Character,
                          models.Universe.name.label('universe'),
                          models.Place.name.label('place_of_birth')) \
        .join(models.Character.universe) \
        .outerjoin(models.Character.place_of_birth)

    # download all data as a pandas DataFrame, index it by the character ID
    characters = cl.df_query(query).set_index('id')

    # query the number of movie appearances per character
    query = session.query(sa.func.count(models.MovieAppearance.id).label('movie_appearances'),
                          models.MovieAppearance.character_id) \
        .group_by(models.MovieAppearance.character_id)

    appearances = cl.df_query(query).set_index('character_id')

    # join both tables, sort by name
    df = characters.join(appearances, how='left').sort_values(by='name')

    # drop the foreign key columns (have no meaning outside our DB)
    df = df.drop(['universe_id', 'place_of_birth_id'], axis=1)

    # write output as both CSV and Excel; do not include index column
    df.to_csv(path.join(out_dir, "characters.csv"), encoding='utf-8', index=False)
    df.to_excel(path.join(out_dir, "characters.xlsx"), encoding='utf-8', index=False)

    session.close()