Composer report

This template allows you to run an analysis on any composer you want (that MusicBrainz knows about of course). Just fill the name of the composer you want and run all cells!

In [1]:
# for example
composer_name = 'Johannes Brahms'

Setup

In [2]:
%run startup.ipy
Last notebook update: 2018-06-05
Git repo: git@bitbucket.org:loujine/musicbrainz-dataviz.git
Importing libs
Defining database parameters

Defining *sql* helper function
Last database update: 2018-06-02

Python packages versions:
numpy       1.14.3
pandas      0.23.0
sqlalchemy  1.2.8
CPython 3.7.0b5
IPython 6.4.0

Work list

In [3]:
def work_list(composer_name):
    composer = sql("""
SELECT gid AS mbid,
       name
  FROM artist
 WHERE name = %(composer_name)s;
    """, composer_name=composer_name)

    works = sql("""
SELECT w.name            AS work_name,
       lt.text_value     AS catalog_no,
       wt.name           AS work_type,
       la.name           AS language,
       watav.value       AS key,
       to_date(to_char(l.begin_date_year, '9999') ||
               to_char(COALESCE(l.end_date_month, 1), '99') ||
               to_char(COALESCE(l.end_date_day, 1), '99'), 'YYYY MM DD') AS start,
       to_date(to_char(l.end_date_year, '9999') ||
               to_char(COALESCE(l.end_date_month, 1), '99') ||
               to_char(COALESCE(l.end_date_day, 1), '99'), 'YYYY MM DD') AS end,
       w.gid             AS mbid
  FROM work          AS w
  JOIN l_artist_work AS law ON w.id = law.entity1
  JOIN artist        AS a   ON a.id = law.entity0
  JOIN link          AS l   ON l.id = law.link
LEFT OUTER JOIN l_series_work                     AS lsw ON w.id = lsw.entity1
LEFT OUTER JOIN series                            AS s   ON s.id = lsw.entity0
LEFT OUTER JOIN link_attribute_text_value         AS lt  ON lt.link = lsw.link
LEFT OUTER JOIN work_language                     AS wl  ON wl.work = w.id
LEFT OUTER JOIN language                          AS la  ON la.id = wl.language
LEFT OUTER JOIN work_type                         AS wt  ON w.type = wt.id
LEFT OUTER JOIN work_attribute                    AS wa  ON wa.work = w.id
LEFT OUTER JOIN work_attribute_type               AS wat   ON wat.id = wa.work_attribute_type
LEFT OUTER JOIN work_attribute_type_allowed_value AS watav ON watav.id = wa.work_attribute_type_allowed_value
 WHERE a.gid = %(composer_mbid)s
 ORDER BY start, work_name;
    """, composer_mbid=composer.mbid[0])

    works['url'] = works.mbid.apply(mb_work_link)
    print('10 first works:')
    iplot(ff.create_table(works[['start', 'work_name', 'url']].head(10)))
    return works

works = work_list(composer_name)
10 first works:

Work chronology

In [4]:
df = works[['start', 'work_name']].groupby(works.start.dropna().map(lambda x: x.year))
count = df.count()['work_name']
# concatenate work names composed on the same year
text = df.agg(lambda s: '<br>'.join(s)).work_name

iplot({'data': [{'type': 'bar', 'x': count.index, 'y': count.values, 'text': text}],
       'layout': {'title': "Chronology of {}'s works".format(composer_name)}})

Work statistics

In [5]:
def work_stat(works):
    types = works.groupby('work_type').count()
    iplot({'data': [{'type': 'pie', 'values': types.mbid,
                     'labels': types.index, 'direction': 'clockwise'}],
           'layout': {'title': "{}'s works by type".format(composer_name)}})

    language = works.groupby('language').count()
    iplot({'data': [{'type': 'pie', 'values': language.mbid,
                     'labels': language.index, 'direction': 'clockwise'}],
           'layout': {'title': "{}'s works by language".format(composer_name)}})

    key = works.groupby('key').count()
    iplot({'data': [{'type': 'pie', 'values': key.mbid,
                     'labels': key.index, 'direction': 'clockwise'}],
           'layout': {'title': "{}'s works by key".format(composer_name)}})
    
work_stat(works)

Catalogue

In [7]:
cat = works[['catalog_no', 'work_name']].sort_values(by='catalog_no').dropna()
iplot(ff.create_table(cat[cat.catalog_no.str.startswith('op.')].head(10)))