Big*_*Ben 5 python matplotlib pandas
给定一个带有竖线分隔系列的数据框:
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']})
Run Code Online (Sandbox Code Playgroud)
或以数据格式:
year genre
0 1960 Drama|Romance|Thriller
1 1960 Spy|Mystery|Bio
2 1961 Drama|Romance
3 1961 Drama|Romance
4 1961 Drama|Spy
Run Code Online (Sandbox Code Playgroud)
我可以将genre系列拆分为str.split(如关于 SO 的许多类似问题所示)。
但是,我也想在今年组和返回的计数Drama,Romance,Thriller,等了新列,每列特殊的一年。
我的初步尝试:
df_split = df.groupby('year')['genre'].apply(lambda x: x.str.split('|', expand=True).reset_index(drop=True))
Run Code Online (Sandbox Code Playgroud)
返回
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
Run Code Online (Sandbox Code Playgroud)
但是如何按年份在其自己的列中获得每个独特类型的数量?
我可以使用独特的流派
genres = pd.unique(df['genre'].str.split('|', expand=True).stack())
Run Code Online (Sandbox Code Playgroud)
但我仍然不确定如何将这些类型作为单独的系列,按年份进行计数。
我想要的最终输出是:
Drama Romance Thriller Spy Mystery Bio
1960 1 1 1 1 1 1
1961 3 2 0 1 0 0
Run Code Online (Sandbox Code Playgroud)
每个独特的流派都是它自己的系列,按年份计算相应的数量。
这也很可能是 XY 问题。我的最终目标是制作一个百分比堆积面积图。假设df_split有所需的转换,我想做:
df_perc = df_split.divide(df_split.sum(axis=1), axis=0)
Run Code Online (Sandbox Code Playgroud)
返回
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
Run Code Online (Sandbox Code Playgroud)
进而
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()
Run Code Online (Sandbox Code Playgroud)
给出输出:
我们可以使用一些简单的重塑和聚合来获得您想要的结果:
(df.assign(genre=df['genre'].str.split('|'))
.explode('genre')
.groupby('year')['genre']
.value_counts(normalize=True)
.unstack(fill_value=0))
genre Bio Drama Mystery Romance Spy Thriller
year
1960 0.166667 0.166667 0.166667 0.166667 0.166667 0.166667
1961 0.000000 0.500000 0.000000 0.333333 0.166667 0.000000
Run Code Online (Sandbox Code Playgroud)
从这里您可以通过绘制面积图来完成:
(df.assign(genre=df['genre'].str.split('|'))
.explode('genre')
.groupby('year')['genre']
.value_counts(normalize=True)
.unstack(fill_value=0)
.plot
.area())
Run Code Online (Sandbox Code Playgroud)
怎么运行的
首先跨行分解数据:
df.assign(genre=df['genre'].str.split('|')).explode('genre')
year genre
0 1960 Drama
0 1960 Romance
0 1960 Thriller
1 1960 Spy
1 1960 Mystery
1 1960 Bio
2 1961 Drama
2 1961 Romance
3 1961 Drama
3 1961 Romance
4 1961 Drama
4 1961 Spy
Run Code Online (Sandbox Code Playgroud)
接下来,执行 agroupby并获取标准化计数:
_.groupby('year')['genre'].value_counts(normalize=True)
year genre
1960 Bio 0.166667
Drama 0.166667
Mystery 0.166667
Romance 0.166667
Spy 0.166667
Thriller 0.166667
1961 Drama 0.500000
Romance 0.333333
Spy 0.166667
Name: genre, dtype: float64
Run Code Online (Sandbox Code Playgroud)
接下来,取消堆叠结果:
_.unstack(fill_value=0)
genre Bio Drama Mystery Romance Spy Thriller
year
1960 0.166667 0.166667 0.166667 0.166667 0.166667 0.166667
1961 0.000000 0.500000 0.000000 0.333333 0.166667 0.000000
Run Code Online (Sandbox Code Playgroud)
最后,绘制
_.plot.area()
Run Code Online (Sandbox Code Playgroud)