Given a dataframe with a pipe-delimited series:
import pandas as pd
import matplotlib.pyplot as plt
df = pd.DataFrame({'year': [1960, 1960, 1961, 1961, 1961],
'genre': ['Drama|Romance|Thriller',
'Spy|Mystery|Bio',
'Drama|Romance',
'Drama|Romance',
'Drama|Spy']})
Or in data format:
year genre
0 1960 Drama|Romance|Thriller
1 1960 Spy|Mystery|Bio
2 1961 Drama|Romance
3 1961 Drama|Romance
4 1961 Drama|Spy
I can split the genre series with str.split (as demonstrated in many similar questions on SO).
But I would also like to group by the year and return the count of Drama, Romance, Thriller, and so on for each unique year in new columns.
My initial attempt:
df_split = df.groupby('year')['genre'].apply(lambda x: x.str.split('|', expand=True).reset_index(drop=True))
which returns
0 1 2
year
1960 0 Drama Romance Thriller
1 Spy Mystery Bio
1961 0 Drama Romance NaN
1 Drama Romance NaN
2 Drama Spy NaN
but then how to get the count of each unique genre in its own column, by year?
I can get the unique genres using
genres = pd.unique(df['genre'].str.split('|', expand=True).stack())
but am still unsure of how to get the genres as separate series, with their counts by year.
The final output I'd like is:
Drama Romance Thriller Spy Mystery Bio
1960 1 1 1 1 1 1
1961 3 2 0 1 0 0
where each unique genre is its own series, with its corresponding count by year.
This may also very well also be an X-Y problem. My end goal is to produce a percentage stacked-area chart. Assuming df_split has the required transformation, I'd like to do:
df_perc = df_split.divide(df_split.sum(axis=1), axis=0)
which returns
Drama Romance Thriller Spy Mystery Bio
1960 0.166667 0.166667 0.166667 0.166667 0.166667 0.166667
1961 0.500000 0.333333 0.000000 0.166667 0.000000 0.000000
and then
plt.stackplot(df_perc.index, *[ts for col, ts in df_perc.iteritems()],
labels=df_perc.columns)
plt.gca().set_xticks(df_perc.index)
plt.margins(0)
plt.legend()
giving the output:
