准备工作 一、关联(Correlation)关系图 1、散点图(Scatter plot) 2、边界气泡图(Bubble plot with Encircling) 3、散点图添加趋势线(Scatter plot with linear regression line of best fit) 4、分面散点图添加趋势线(Each regression line in its own column) 5、抖动图(Jittering with stripplot) 6、计数图(Counts Plot) 7、边缘直方图(Marginal Histogram) 8、边缘箱图(Marginal Boxplot) 9、相关性热图(Correllogram) 10、矩阵图 (Pairwise Plot)
六、变化(Change)关系图 36、时间序列图(Time Series Plot) 37、波峰和波谷添加注释的时间序列图(Time Series with Peaks and Troughs Annotated) 38、自相关和部分自相关图(Autocorrelation (ACF) and Partial Autocorrelation (PACF) Plot) 39、交叉相关图(Cross Correlation plot) 40、时间序列分解图(Time Series Decomposition Plot) 41、多重时间序列图(Multiple Time Series) 42、双坐标系时间序列图(Plotting with different scales using secondary Y axis) 43、带误差阴影的时间序列图(Time Series with Error Bands) 44、堆积面积图(Stacked Area Chart) 45、非堆积面积图(Area Chart UnStacked) 46、日历热力图(Calendar Heat Map) 47、季节图(Seasonal Plot)
import numpy as np import pandas as pd import matplotlib as mpl import matplotlib.pyplot as plt import seaborn as sns import warnings warnings.filterwarnings(action='once')
# Prepare Data
# Create as many colors as there are unique midwest['category'] categories = np.unique(midwest['category']) colors = [ plt.cm.Set1(i / float(len(categories) - 1)) for i in range(len(categories)) ]
# Draw Plot for Each Category plt.figure(figsize=(10, 6), dpi=100, facecolor='w', edgecolor='k')
for i, category in enumerate(categories): plt.scatter('area', 'poptotal', data=midwest.loc[midwest.category == category, :], s=20, c=colors[i], label=str(category))
from matplotlib import patches from scipy.spatial import ConvexHull #更多参考scipy.spatial.ConvexHull sns.set_style("whitegrid")
# Step 1: Prepare Data midwest = pd.read_csv("./datasets/midwest_filter.csv")
# As many colors as there are unique midwest['category'] categories = np.unique(midwest['category']) colors = [ plt.cm.Set1(i / float(len(categories) - 1)) for i in range(len(categories)) ]
# Step 2: Draw Scatterplot with unique color for each category fig = plt.figure(figsize=(10, 6), dpi=80, facecolor='w', edgecolor='k')
for i, category in enumerate(categories): plt.scatter('area', 'poptotal', data=midwest.loc[midwest.category == category, :], s='dot_size', c=colors[i], label=str(category), edgecolors='black', linewidths=.5)
# Decorations sns.set(style="whitegrid", font_scale=1.5) gridobj.set(xlim=(0.5, 7.5), ylim=(10, 50)) gridobj.fig.set_size_inches(10, 6) plt.title("Scatterplot with line of best fit grouped by number of cylinders") plt.show()
# Each line in its own column gridobj = sns.lmplot(x="displ", y="hwy", data=df_select, height=7, robust=True, palette='Set1', col="cyl", scatter_kws=dict(s=60, linewidths=.7, edgecolors='black'))
#友情提示:当matplotlib>=3.2出现报错ValueError: s must be a scalar, or the same size as x and y时 # Import Data df = pd.read_csv("./datasets/mpg_ggplot2.csv") df_counts = df.groupby(['hwy', 'cty']).size().reset_index(name='counts') # Draw Stripplot fig, ax = plt.subplots(figsize=(10, 6), dpi=80) sns.stripplot(df_counts.cty, df_counts.hwy, size=df_counts.counts * 2, ax=ax, palette='Set1')
# Decorations sns.set(style="whitegrid", font_scale=1.1) plt.title('Counts Plot - Size of circle is bigger as more points overlap') plt.show()
# Scatterplot on main ax ax_main.scatter('displ', 'hwy', s=df.cty * 5, c=df.manufacturer.astype('category').cat.codes, alpha=.9, data=df, cmap="Set1", edgecolors='black', linewidths=.5)
# Add a graph in each part sns.boxplot(df.hwy, ax=ax_right, orient="v", linewidth=1, palette='Set1') sns.boxplot(df.displ, ax=ax_bottom, orient="h", linewidth=1, palette='Set1')
# Decorations ------------------ # Remove x axis name for the boxplot ax_bottom.set(xlabel='') ax_right.set(ylabel='')
# Main Title, Xlabel and YLabel ax_main.set(title='Scatterplot with Histograms \n displ vs hwy', xlabel='displ', ylabel='hwy')
# Set font size of different components ax_main.title.set_fontsize(12) for item in ([ax_main.xaxis.label, ax_main.yaxis.label] + ax_main.get_xticklabels() + ax_main.get_yticklabels()): item.set_fontsize(11)
# Decorations plt.gca().set(ylabel='$Model, xlabel='$Mileage) plt.yticks(df.index, df.cars, fontsize=12) plt.xticks(fontsize=12) plt.title('Diverging Bars of Car Mileage') plt.grid(linestyle='--', alpha=0.5) plt.show()
12、发散型文本图(Diverging Texts)-水平方向
和上一个图的区别是该图在柱子上添加了数值文本。
# Prepare Data df = pd.read_csv("./datasets/mtcars.csv") #df['Species'] = x = df.loc[:, ['mpg']] df['mpg_z'] = (x - x.mean())/x.std() df['colors'] = ['red'if x 0 else'green'for x in df['mpg_z']] df.sort_values('mpg_z', inplace=True) df.reset_index(inplace=True)
# Draw plot plt.figure(figsize=(10,8), dpi= 80) plt.hlines(y=df.index, xmin=0, xmax=df.mpg_z,color=df.colors, alpha=0.8, linewidth=5) for x, y, tex in zip(df.mpg_z, df.index, df.mpg_z): t = plt.text(x, y, round(tex, 2), horizontalalignment='right'if x 0 else'left', verticalalignment='center', fontdict={'color':'black'if x 0 else'black', 'size':10})
# Decorations plt.yticks(df.index, df.cars, fontsize=12) plt.xticks(fontsize=10) plt.title('Diverging Text Bars of Car Mileage', fontdict={'size':15}) plt.grid(linestyle='--', alpha=0.5) plt.xlim(-2.5, 2.5) plt.show() #垂直版感兴趣可以改改就可以了
13、发散型文本图(Diverging Texts)-垂直方向
# Prepare Data df = pd.read_csv("./datasets/mtcars.csv") x = df.loc[:, ['mpg']] df['mpg_z'] = (x - x.mean()) / x.std() df['colors'] = ['red'if x 0 else'green'for x in df['mpg_z']] df.sort_values('mpg_z', inplace=True) df.reset_index(inplace=True)
# Draw plot plt.figure(figsize=(10, 6), dpi=80) plt.vlines(x=df.index, ymin=0, ymax=df.mpg_z, color=df.colors, alpha=0.8, linewidth=5) for y, x, tex in zip(df.mpg_z, df.index, df.mpg_z): t = plt.text(x, y+0.2, round(tex, 1), horizontalalignment='center', fontdict={ 'color': 'black'if x 0 else'black', 'size': 8 })
# Decorations plt.xticks(df.index, df.cars, fontsize=12, rotation=90) plt.yticks(fontsize=12) plt.title('Diverging Text Bars of Car Mileage', fontdict={'size': 12}) plt.grid(linestyle='--', alpha=0.5) plt.show()
14、发散型点图(Diverging Dot Plot)
与发散性文本图的区别是缺失柱子,减少了组之间的对比差异。
# Prepare Data df = pd.read_csv("./datasets/mtcars.csv") x = df.loc[:, ['mpg']] df['mpg_z'] = (x - x.mean()) / x.std() df['colors'] = ['red'if x 0 else'darkgreen'for x in df['mpg_z']] df.sort_values('mpg_z', inplace=True) df.reset_index(inplace=True)
# Draw plot plt.figure(figsize=(12, 10), dpi=80) plt.scatter(df.mpg_z, df.index, s=250, alpha=.6, color=df.colors) for x, y, tex in zip(df.mpg_z, df.index, df.mpg_z): t = plt.text(x, y, round(tex, 1), horizontalalignment='center', verticalalignment='center', fontdict={'color': 'black','size': '10'})
#comparing the ‘Before’ and ‘After’ positions of a given person/item import matplotlib.lines as
mlines # Import Data df = pd.read_csv("./datasets/gdppercap.csv")
left_label = [ str(c) + ', ' + str(round(y)) for c, y in zip(df.continent, df['1952']) ] right_label = [ str(c) + ', ' + str(round(y)) for c, y in zip(df.continent, df['1957']) ] klass = [ 'red'if (y1 - y2) 0 else'green' for y1, y2 in zip(df['1952'], df['1957']) ]
# draw line # https://stackoverflow.com/questions/36470343/how-to-draw-a-line-with-matplotlib/36479941 defnewline(p1, p2, color='black'): ax = plt.gca() l = mlines.Line2D([p1[0], p2[0]], [p1[1], p2[1]], color='red'if p1[1] - p2[1] > 0else'green', marker='o', markersize=6) ax.add_line(l) return l
# Decoration ax.set_title("Slopechart: Comparing GDP Per Capita between 1952 vs 1957", fontdict={'size': 18}) ax.set(xlim=(0, 4), ylim=(0, 14000), ylabel='Mean GDP Per Capita') plt.ylabel('Mean GDP Per Capita', fontsize=15) ax.set_xticks([1, 3]) ax.set_xticklabels(["1952", "1957"], fontdict={'size': 15, 'weight': 700}) plt.yticks(np.arange(500, 13000, 2000), fontsize=12)
# Line Segments for i, p1, p2 in zip(df['index'], df['pct_2013'], df['pct_2014']): newline([p1, i], [p2, i])
# Decoration ax.set_facecolor('#f8f2e4') ax.set_title("Dumbell Chart: Pct Change - 2013 vs 2014", fontdict={'size': 18}) ax.set(xlim=(0, .25), ylim=(-1, 27), ylabel='Mean GDP Per Capita') plt.ylabel('Mean GDP Per Capita', fontsize=15) plt.yticks(fontsize=15) ax.set_xticks([.05, .1, .15, .20]) ax.set_xticklabels(['5%', '15%', '20%', '25%'], fontdict={'size': 15}) plt.show()
四、分布(Distribution)关系图
21、连续变量堆积直方图(Stacked Histogram for Continuous Variable)
该图展示给定连续变量的频率分布。
# Import Data df = pd.read_csv("./datasets/mpg_ggplot2.csv")
# Prepare data x_var = 'displ' groupby_var = 'class' df_agg = df.loc[:, [x_var, groupby_var]].groupby(groupby_var) vals = [df[x_var].values.tolist() for i, df in df_agg]
# Draw plt.figure(figsize=(10, 6), dpi=80) colors = [plt.cm.Set1(i / float(len(vals) - 1)) for i in range(len(vals))] n, bins, patches = plt.hist(vals, 30, stacked=True, density=False, color=colors[:len(vals)])
# Decoration plt.legend({ group: col for group, col in zip( np.unique(df[groupby_var]).tolist(), colors[:len(vals)]) }) plt.title(f"Stacked Histogram of ${x_var}$ colored by ${groupby_var}$", fontsize=22) plt.xlabel(x_var) plt.ylabel("Frequency") #plt.ylim(0, 25) plt.xticks(ticks=bins[::3], labels=[round(b, 1) for b in bins[::3]]) plt.show()
22、类别变量堆积直方图(Stacked Histogram for Categorical Variable)
该图展示给定类别变量的频率分布。
# Import Data df = pd.read_csv("./datasets/mpg_ggplot2.csv")
# Prepare data x_var = 'manufacturer' groupby_var = 'class' df_agg = df.loc[:, [x_var, groupby_var]].groupby(groupby_var) vals = [df[x_var].values.tolist() for i, df in df_agg]
# Draw plt.figure(figsize=(10, 6), dpi=80) colors = [plt.cm.Set1(i / float(len(vals) - 1)) for i in range(len(vals))] n, bins, patches = plt.hist(vals, df[x_var].unique().__len__(), stacked=True, density=False, color=colors[:len(vals)])
# Decoration plt.legend({ group: col for group, col in zip( np.unique(df[groupby_var]).tolist(), colors[:len(vals)]) }) plt.title(f"Stacked Histogram of ${x_var}$ colored by ${groupby_var}$", fontsize=22) plt.xlabel(x_var) plt.ylabel("Frequency") plt.ylim(0, 40) plt.xticks(ticks=bins, labels=np.unique(df[x_var]).tolist(), rotation=90, horizontalalignment='left') plt.show()
# Mean and Median city mileage by make df = df_raw[['cty', 'manufacturer']].groupby('manufacturer').apply(lambda x: x.mean()) df.sort_values('cty', ascending=False, inplace=True) df.reset_index(inplace=True) df_median = df_raw[['cty', 'manufacturer' ]].groupby('manufacturer').apply(lambda x: x.median())
# Read data df = pd.read_csv("./datasets/email_campaign_funnel.csv")
# Draw Plot plt.figure(figsize=(12, 8), dpi=80) group_col = 'Gender' order_of_bars = df.Stage.unique()[::-1] colors = [ plt.cm.Set1(i / float(len(df[group_col].unique()) - 1)) for i in range(len(df[group_col].unique())) ]
for c, group in zip(colors, df[group_col].unique()): sns.barplot(x='Users', y='Stage', data=df.loc[df[group_col] == group, :], order=order_of_bars, color=c, label=group)
# Decorations plt.xlabel("$Users$") plt.ylabel("Stage of Purchase") plt.yticks(fontsize=12) plt.title("Population Pyramid of the Marketing Funnel", fontsize=18) plt.legend() plt.show()
# Prepare Data df = df_raw.groupby('class').size().reset_index(name='counts') n_categories = df.shape[0] colors = [plt.cm.Set1(i / float(n_categories)) for i in range(n_categories)]
from pywaffle import Waffle # Prepare Data # By Class Data df_class = df_raw.groupby('class').size().reset_index(name='counts_class') n_categories = df_class.shape[0] colors_class = [ plt.cm.Set3(i / float(n_categories)) for i in range(n_categories) ]
# By Cylinders Data df_cyl = df_raw.groupby('cyl').size().reset_index(name='counts_cyl') n_categories = df_cyl.shape[0] colors_cyl = [ plt.cm.Set1(i / float(n_categories)) for i in range(n_categories) ]
# By Make Data df_make = df_raw.groupby('manufacturer').size().reset_index(name='counts_make') n_categories = df_make.shape[0] colors_make = [ plt.cm.tab20b(i / float(n_categories)) for i in
range(n_categories) ]
# Make the plot with pandas df.plot(kind='pie', subplots=True, figsize=(10, 10)) plt.title("Pie Chart of Vehicle Class - Bad") plt.ylabel("") plt.show()
该图将时间序列分解为趋势、季节和残差分量(trend, seasonal and residual components.)。
from statsmodels.tsa.seasonal import seasonal_decompose from dateutil.parser import parse
# Import Data df = pd.read_csv('./datasets/AirPassengers.csv') dates = pd.DatetimeIndex([parse(d).strftime('%Y-%m-01') for d in df['date']]) df.set_index(dates, inplace=True)
# Decompose result = seasonal_decompose(df['value'], model='multiplicative')
# Plot plt.figure(figsize=(12, 7), dpi=80) #plt.rcParams.update({'figure.figsize': (10, 10)}) result.plot().suptitle('Time Series Decomposition of Air Passengers') plt.show()
41、多重时间序列图(Multiple Time Series)
# Import Data df = pd.read_csv('./datasets/mortality.csv')
# Define the upper limit, lower limit, interval of Y axis and colors y_LL = 100 y_UL = int(df.iloc[:, 1:].max().max() * 1.1) y_interval = 400 mycolors = ['tab:red', 'tab:blue', 'tab:green', 'tab:orange']
plt.title('Number of Deaths from Lung Diseases in the UK (1974-1979)', fontsize=18) plt.yticks(range(y_LL, y_UL, y_interval), [str(y) for y in range(y_LL, y_UL, y_interval)], fontsize=12) plt.xticks(range(0, df.shape[0], 12), df.date.values[::12], horizontalalignment='left', rotation=45, fontsize=12) plt.ylim(y_LL, y_UL) plt.xlim(-2, 80) plt.show()
42、双坐标系时间序列图(Plotting with different scales using secondary Y axis)
# Import Data df = pd.read_csv("./datasets/economics.csv")
x = df['date'] y1 = df['psavert'] y2 = df['unemploy']
# ax2 (right Y axis) ax2.set_ylabel("# Unemployed (1000's)", color='#01a2d9', fontsize=16) ax2.tick_params(axis='y', labelcolor='#01a2d9') ax2.set_xticks(np.arange(0, len(x), 60)) ax2.set_xticklabels(x[::60], rotation=90, fontdict={'fontsize': 10}) ax2.set_title( "Personal Savings Rate vs Unemployed: Plotting in Secondary Y Axis", fontsize=18) fig.tight_layout() plt.show()
43、带误差阴影的时间序列图(Time Series with Error Bands)
from dateutil.parser import parse from scipy.stats import sem
# Import Data df_raw = pd.read_csv('./datasets/orders_45d.csv', parse_dates=['purchase_time', 'purchase_date'])
# Prepare Data: Daily Mean and SE Bands df_mean = df_raw.groupby('purchase_date').quantity.mean() df_se = df_raw.groupby('purchase_date').quantity.apply(sem).mul(1.96)
# Plot plt.figure(figsize=(10, 6), dpi=80) plt.ylabel("# Daily Orders", fontsize=12) x = [d.date().strftime('%Y-%m-%d') for d in df_mean.index] plt.plot(x, df_mean, color="#c72e29", lw=2) plt.fill_between(x, df_mean - df_se, df_mean + df_se, color="#f8f2e4")
# Decorations # Lighten borders plt.gca().spines["top"
].set_alpha(0) plt.gca().spines["bottom"].set_alpha(1) plt.gca().spines["right"].set_alpha(0) plt.gca().spines["left"].set_alpha(1) plt.xticks(x[::6], [str(d) for d in x[::6]], fontsize=12) plt.title( "Daily Order Quantity of Brazilian Retail with Error Bands (95% confidence)", fontsize=14)
# Axis limits s, e = plt.gca().get_xlim() plt.xlim(s, e - 2) plt.ylim(4, 10)
# Draw Horizontal Tick lines for y in range(5, 10, 1): plt.hlines(y, xmin=s, xmax=e, colors='black', alpha=0.5, linestyles="--", lw=0.5)
plt.show()
44、堆积面积图(Stacked Area Chart)
# Import Data df = pd.read_csv('./datasets/nightvisitors.csv')
for i, y in enumerate(years): plt.plot('month', 'value', data=df.loc[df.year == y, :], color=mycolors[i], label=y) plt.text(df.loc[df.year == y, :].shape[0] - .9, df.loc[df.year == y, 'value'][-1:].values[0], y, fontsize=12, color=mycolors[i])