純干貨:手把手教你用Python做數(shù)據(jù)可視化(附代碼)
導(dǎo)讀:制作提供信息的可視化(有時(shí)稱為繪圖)是數(shù)據(jù)分析中的最重要任務(wù)之一??梢暬赡苁翘剿鬟^程的一部分,例如,幫助識(shí)別異常值或所需的數(shù)據(jù)轉(zhuǎn)換,或者為建模提供一些想法。對于其他人來說,構(gòu)建網(wǎng)絡(luò)交互式可視化可能是最終目標(biāo)。Python有很多附加庫可以用來制作靜態(tài)或動(dòng)態(tài)的可視化文件,但是我將主要關(guān)注matplotlib和以它為基礎(chǔ)的庫。
matplotlib是一個(gè)用于生成出版級質(zhì)量圖表(通常是二維的)的桌面繪圖包。該項(xiàng)目由John Hunter于2002年發(fā)起,目的在于在Python環(huán)境下進(jìn)行MATLAB風(fēng)格的繪圖。matplotlib和IPython社區(qū)合作簡化了IPython shell(目前是 Jupyter筆記本)的交互式繪圖。matplotlib支持所有操作系統(tǒng)上的各種GUI后端,還可以將可視化導(dǎo)出為所有常見的矢量和光柵圖形格式(PDF,SVG,JPG,PNG,BMP,GIF等)。
隨著時(shí)間的推移,matplotlib已經(jīng)產(chǎn)生了一些數(shù)據(jù)可視化的附加工具包,使用matplotlib進(jìn)行底層繪圖。
學(xué)習(xí)以下示例代碼最簡單的方式就是在Jupyter notebook中使用交互式繪圖。在進(jìn)行設(shè)置時(shí),需要在Jupyter notebook中執(zhí)行以下語句:
%matplotlib notebook
簡明matplotlib API入門
在使用matplotlib時(shí),我們使用以下的導(dǎo)入慣例:
In [11]: import matplotlib.pyplot as plt
在Jupyter中運(yùn)行%matplotlib notebook (或在IPython中運(yùn)行%matplotlib ),我們就可以嘗試生成一個(gè)簡單的圖形。如果所有的設(shè)置都正確,則一個(gè)像圖1的圖形就會(huì)出現(xiàn):
In [12]: import numpy as np
In [13]: data = np.arange(10)
In [14]: data
Out[14]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [15]: plt.plot(data)

▲圖1 簡單的線性圖
盡管seaborn等庫和pandas內(nèi)建的繪圖函數(shù)可以處理大部分繪圖的普通細(xì)節(jié),但如果你想在提供的函數(shù)選項(xiàng)之外進(jìn)行定制則需要學(xué)習(xí)一些matplotlib的AIP。
本文沒有足夠的篇幅來對matplotlib的功能寬度和深度進(jìn)行全面介紹。但介紹的內(nèi)容應(yīng)該是足以使你入門的。matplotlib的可視化作品庫和文檔是學(xué)習(xí)高級功能的最佳資源。
圖片與子圖
matplotlib所繪制的圖位于圖片(Figure)對象中。你可以使用plt.figure生成一個(gè)新的圖片:
In [16]: fig = plt.figure()
在IPython中,一個(gè)空白的繪圖窗口就會(huì)出現(xiàn),但在Jupyter中則沒有任何顯示,直到我們使用一些其他命令。plt.figure有一些選項(xiàng),比如figsize是確保圖片有一個(gè)確定的大小以及存儲(chǔ)到硬盤時(shí)的長寬比。
你不能使用空白的圖片進(jìn)行繪圖。你需要使用add_subplot創(chuàng)建一個(gè)或多個(gè)子圖(subplot):
In [16]: fig = plt.figure()
In [17]: ax1 = fig.add_subplot(2, 2, 1)
上面代碼的意思是圖片應(yīng)該是2*2的(最多四個(gè)圖形),并且我們選擇了四個(gè)圖形中的第一個(gè)(序號(hào)從1開始)。如果你接著創(chuàng)建了兩個(gè)子圖,你將會(huì)獲得看上去類似圖2的可視化:
In [18]: ax2 = fig.add_subplot(2, 2, 2)
In [19]: ax3 = fig.add_subplot(2, 2, 3)

▲圖2 一個(gè)帶有三個(gè)子圖的空白matplotlib圖片
使用Jupyter notebook時(shí)有個(gè)細(xì)節(jié)需要注意,在每個(gè)單元格運(yùn)行后,圖表被重置,因此對于更復(fù)雜的圖表,你必須將所有的繪圖命令放在單個(gè)的notebook單元格中。
我們將下面這些代碼在同一個(gè)單元格中運(yùn)行:
fig = plt.figure()
ax1 = fig.add_subplot(2, 2, 1)
ax2 = fig.add_subplot(2, 2, 2)
ax3 = fig.add_subplot(2, 2, 3)
當(dāng)你輸入繪圖命令plt.plot([1.5, 3.5, -2, 1.6]) ,matplotlib會(huì)在最后一個(gè)圖片和子圖(如果需要的話就創(chuàng)建一個(gè))上進(jìn)行繪制,從而隱藏圖片和子圖的創(chuàng)建。因此,如果我們添加了下面的代碼,你會(huì)得到形如圖3的可視化:
In [20]: plt.plot(np.random.randn(50).cumsum(), 'k--')

▲圖3 單個(gè)子圖繪制的數(shù)據(jù)可視化
'k--'是用于繪制黑色分段線的style選項(xiàng)。fig.add_subplot返回的對象是AxesSubplot對象,使用這些對象你可以直接在其他空白的子圖上調(diào)用對象的實(shí)例方法進(jìn)行繪圖(參考圖4):
In [21]: _ = ax1.hist(np.random.randn(100), bins=20, color='k', alpha=0.3)
In [22]: ax2.scatter(np.arange(30), np.arange(30) + 3 * np.random.randn(30))

▲圖4 增加子圖后的數(shù)據(jù)可視化
你可以在matplotlib的官方文檔中找到完整的圖形類型。
使用子圖網(wǎng)絡(luò)創(chuàng)建圖片是非常常見的任務(wù),所以matplotlib包含了一個(gè)便捷方法plt.subplots,它創(chuàng)建一個(gè)新的圖片,然后返回要給包含了已生成子圖對象的NumPy數(shù)組:
In [24]: fig, axes = plt.subplots(2, 3)
In [25]: axes
Out[25]:
array([[<matplotlib.axes._subplots.AxesSubplot object at 0x7fb626374048>,
<matplotlib.axes._subplots.AxesSubplot object at 0x7fb62625db00>,
<matplotlib.axes._subplots.AxesSubplot object at 0x7fb6262f6c88>],
[<matplotlib.axes._subplots.AxesSubplot object at 0x7fb6261a36a0>,
<matplotlib.axes._subplots.AxesSubplot object at 0x7fb626181860>,
<matplotlib.axes._subplots.AxesSubplot object at 0x7fb6260fd4e0>]], dtype
=object)
| 參數(shù) | 描述 |
|---|---|
| nrows | 子圖的行數(shù) |
| ncols | 子圖的列數(shù) |
| sharex | 所有子圖使用相同的x軸刻度(調(diào)整xlim會(huì)影響所有子圖) |
| sharey | 所有子圖使用相同的y軸刻度(調(diào)整ylim會(huì)影響所有子圖) |
| subplot_kw | 傳入add_subplot的關(guān)鍵字參數(shù)字典,用于生成子圖 |
| **fig_kw | 在生成圖片時(shí)使用的額外關(guān)鍵字參數(shù),例如plt.subplots(2, 2, figsize=(8,6)) |
▲表1 pyplot.subplots選項(xiàng)
調(diào)整子圖周圍的間距
默認(rèn)情況下,matplotlib會(huì)在子圖的外部和子圖之間留出一定的間距。這個(gè)間距都是相對于圖的高度和寬度來指定的,所以如果你通過編程或手動(dòng)使用GUI窗口來調(diào)整圖的大小,那么圖就會(huì)自動(dòng)調(diào)整。你可以使用圖對象上的subplots_adjust方法更改間距,也可以用作頂層函數(shù):
subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=None)
wspace和hspace分別控制的是圖片的寬度和高度百分比,以用作子圖間的間距。下面是一個(gè)小例子,我將這個(gè)間距一直縮小到零(見圖5) :
fig, axes = plt.subplots(2, 2, sharex=True, sharey=True)
for i in range(2):
for j in range(2):
axes[i, j].hist(np.random.randn(500), bins=50, color='k', alpha=0.5)
plt.subplots_adjust(wspace=0, hspace=0)

▲圖5 沒有內(nèi)部子圖間隔的數(shù)據(jù)可視化
你可能會(huì)注意到軸標(biāo)簽是存在重疊的。matplotlib并不檢查標(biāo)簽是否重疊,因此在類似情況下你需要通過顯式指定刻度位置和刻度標(biāo)簽的方法來修復(fù)軸標(biāo)簽。
顏色、標(biāo)記和線類型
matplotlib的主函數(shù)plot接收帶有x和y周的數(shù)組以及一些可選的字符串縮寫參數(shù)來指明顏色和線類型。例如,要用綠色破折號(hào)繪制x對y的線,你需要執(zhí)行:
ax.plot(x, y, 'g--')
這種在字符串中指定顏色和線條樣式的方式是方便的; 在實(shí)踐中,如果你以編程方式創(chuàng)建繪圖,則可能不希望將字符串混合在一起以創(chuàng)建具有所需樣式的圖表。同樣的圖表可以使用更為顯式的方式來表達(dá):
ax.plot(x, y, 'g--')
ax.plot(x, y, linestyle='--', color='g')
有很多顏色縮寫被用于常用顏色,但是你可以通過指定十六進(jìn)制顏色代碼的方式來指定任何顏色(例如'#CECECE' )。參考plot函數(shù)的文檔字符串可以看到全部的線類型(在IPython或Jupyter中使用plot? )。
折線圖還可以有標(biāo)記用來凸顯實(shí)際的的數(shù)據(jù)點(diǎn)。由于matplotlib創(chuàng)建了一個(gè)連續(xù)性折線圖,插入點(diǎn)之間有時(shí)并不清除點(diǎn)在哪。標(biāo)記可以是樣式字符串的一部分,樣式字符串中線類型、標(biāo)記類型必須跟在顏色后面(參考圖6):
In [30]: from numpy.random import randn
In [31]: plt.plot(randn(30).cumsum(), 'ko--')

▲圖6 帶有標(biāo)記的折線圖
上面的代碼可以寫的更為顯式:
plot(randn(30).cumsum(), color='k', linestyle='dashed', marker='o')
對于折線圖,你會(huì)注意到后續(xù)的點(diǎn)默認(rèn)是線性內(nèi)插的??梢酝ㄟ^drawstyle選項(xiàng)進(jìn)行更改(圖7):
In [33]: data = np.random.randn(30).cumsum()
In [34]: plt.plot(data, 'k--', label='Default')
Out[34]: [<matplotlib.lines.Line2D at 0x7fb624d86160>]
In [35]: plt.plot(data, 'k-', drawstyle='steps-post', label='steps-post')
Out[35]: [<matplotlib.lines.Line2D at 0x7fb624d869e8>]
In [36]: plt.legend(loc='best')

▲圖7 不同drawstyle選項(xiàng)下的折線圖
你可能會(huì)注意到在運(yùn)行代碼后會(huì)有像 這樣的輸出。matplotlib返回的對象引用了剛剛添加的圖表子組件。很多時(shí)候你可以安全地忽略這些輸出。這里,由于我們向plot傳遞了label,我們可以使用plt.lengend為每條線生成一個(gè)用于區(qū)分的圖例。
無論你在用數(shù)據(jù)繪圖時(shí)是否傳遞了lebel選項(xiàng),你都必須調(diào)用plt.lengend(如果你有軸的引用,也可以用ax.legend)來生成圖例來生成圖例。
刻度、標(biāo)簽和圖例
對于大多數(shù)圖表修飾工作,有兩種主要的方式:使用程序性的pyplot接口(即matplotlib.pyplot)和更多面向?qū)ο蟮脑鷐atplotlib API。
pyplot接口設(shè)計(jì)為交互式使用,包含了像xllim、xtick和xtcklabels等方法。這些方法分別控制了繪圖范圍、刻度位置以及刻度標(biāo)簽。我們可以在兩種方式中使用:
在沒有函數(shù)參數(shù)的情況下調(diào)用,返回當(dāng)前的參數(shù)值(例如plt.xlim()返回當(dāng)前的x軸繪圖范圍 )。
傳入?yún)?shù)的情況下調(diào)用,并設(shè)置參數(shù)值(例如plt.xlim([0, 10])會(huì)將x軸的范圍設(shè)置為0到10)。
所有的這些方法都會(huì)在當(dāng)前活動(dòng)的或最近創(chuàng)建的AxeSubplot上生效。這些方法中的每一個(gè)對應(yīng)于子圖自身的兩個(gè)方法;比如xlim對應(yīng)于ax.get_lim和ax.set_lim。我更傾向于使用subplot的實(shí)例方法,因?yàn)檫@樣更為顯式(尤其是在處理多個(gè)子圖時(shí)),但你當(dāng)然可以使用你覺得更為方便的方式。
1. 設(shè)置標(biāo)題、軸標(biāo)簽、刻度和刻度標(biāo)簽
為了講解軸的自定義,我會(huì)生成一個(gè)簡單圖表,并繪制隨機(jī)漫步(參考圖8):
In [37]: fig = plt.figure()
In [38]: ax = fig.add_subplot(1, 1, 1)
In [39]: ax.plot(np.random.randn(1000).cumsum())

▲圖8 表述x軸(以及軸標(biāo)簽)的簡單圖表
要改變x軸刻度,最簡單的方式是使用set_xticks和set_xticklebels。set_xticks表示在數(shù)據(jù)范圍內(nèi)設(shè)定刻度的位置;默認(rèn)情況下,這些刻度也有標(biāo)簽。但是我們可以使用set_xticklabels為標(biāo)簽賦值:
In [40]: ticks = ax.set_xticks([0, 250, 500, 750, 1000])
In [41]: labels = ax.set_xticklabels(['one', 'two', 'three', 'four', 'five'],
....: rotation=30, fontsize='small')
rotation選項(xiàng)會(huì)將x軸刻度標(biāo)簽旋轉(zhuǎn)30度。最后,set_xlabel會(huì)給x軸一個(gè)名稱,set_titel會(huì)給子圖一個(gè)標(biāo)題(參考圖9的結(jié)果圖):
In [42]: ax.set_title('My first matplotlib plot')
Out[42]: <matplotlib.text.Text at 0x7fb624d055f8>
In [43]: ax.set_xlabel('Stages')

▲圖9 x軸刻度的簡單示例
修改y軸坐標(biāo)是相同過程,將上面示例中的x替換成y即可。軸的類型擁有一個(gè)set方法,允許批量設(shè)置繪圖屬性。根據(jù)之前的示例,我們可以寫如下代碼:
props = {
'title': 'My first matplotlib plot',
'xlabel': 'Stages'
}
ax.set(**props)
2. 添加圖例
圖例是用來區(qū)分繪圖元素的重要內(nèi)容。有多種方式可以添加圖例。最簡單的方式是在添加每個(gè)圖表時(shí)傳遞label參數(shù):
In [44]: from numpy.random import randn
In [45]: fig = plt.figure(); ax = fig.add_subplot(1, 1, 1)
In [46]: ax.plot(randn(1000).cumsum(), 'k', label='one')
Out[46]: [<matplotlib.lines.Line2D at 0x7fb624bdf860>]
In [47]: ax.plot(randn(1000).cumsum(), 'k--', label='two')
Out[47]: [<matplotlib.lines.Line2D at 0x7fb624be90f0>]
In [48]: ax.plot(randn(1000).cumsum(), 'k.', label='three')
Out[48]: [<matplotlib.lines.Line2D at 0x7fb624be9160>]
一旦你運(yùn)行了上面的代碼,你也可以調(diào)用ax.legend()或plt.legend自動(dòng)生成圖例。結(jié)果圖表參見圖10:
In [49]: ax.legend(loc='best')

▲圖10 有三根折線和圖例的簡單圖表
legend方法有多個(gè)其他的位置參數(shù)loc。參考文檔字符串(使用ax.legend?命令)獲取更多信息。
loc參數(shù)告訴matplotlib在哪里放置圖表。如果你不挑剔,'best'是一個(gè)好選項(xiàng),它會(huì)自動(dòng)選擇最合適的位置。如果取消圖例中的元素,不要傳入label參數(shù)或者傳入label='nolegend'。
注釋與子圖加工
除了標(biāo)準(zhǔn)的繪圖類型,你可能還會(huì)想在圖表上繪制自己的注釋,而且注釋中可能會(huì)包含文本、箭頭以及其他圖形。你可以使用text、arrow和annote方法來添加注釋和文本。text在圖表上給定的坐標(biāo)(x, y),根據(jù)可選的定制樣式繪制文本:
ax.text(x, y, 'Hello world!',
family='monospace', fontsize=10)
注釋可以同時(shí)繪制文本和箭頭。作為一個(gè)例子,讓我們繪制標(biāo)普500指數(shù)從2007年來的收盤價(jià)(從雅虎財(cái)經(jīng)獲得數(shù)據(jù)),并在圖表中標(biāo)注從2008到2009年金融危機(jī)中的重要日期。你可以在Jupyter notebook的一個(gè)單元格中復(fù)現(xiàn)這些代碼。參考圖11的代碼運(yùn)行結(jié)果:
from datetime import datetime
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
data = pd.read_csv('examples/spx.csv', index_col=0, parse_dates=True)
spx = data['SPX']
spx.plot(ax=ax, style='k-')
crisis_data = [
(datetime(2007, 10, 11), 'Peak of bull market'),
(datetime(2008, 3, 12), 'Bear Stearns Fails'),
(datetime(2008, 9, 15), 'Lehman Bankruptcy')
]
for date, label in crisis_data:
ax.annotate(label, xy=(date, spx.asof(date) + 75),
xytext=(date, spx.asof(date) + 225),
arrowprops=dict(facecolor='black', headwidth=4, width=2,
headlength=4),
horizontalalignment='left', verticalalignment='top')
# 放大2007 - 2010年
ax.set_xlim(['1/1/2007', '1/1/2011'])
ax.set_ylim([600, 1800])
ax.set_title('Important dates in the 2008-2009 financial crisis')

▲圖11 2008-2009金融危機(jī)中的重要日期
在圖表中有一些重要點(diǎn)需要凸顯:ax.annotate方法可以在指定的x和y坐標(biāo)上繪制標(biāo)簽。我們可以使用set_xlim和set_ylim方法手動(dòng)設(shè)置圖表的邊界,而不是使用matplotlib的默認(rèn)設(shè)置。最后,ax.set_title會(huì)圖表添加了一個(gè)主標(biāo)題。
參考在線的matplotlib展覽館,可以學(xué)習(xí)更多注釋的范例。
繪制圖形時(shí)有更多需要注意的地方。matplotlib含有表示多種常見圖形的對象,這些對象的引用是patches。一些圖形,比如Rectangle(矩形)和Circle(圓形),可以在matplotlib.pyplot中找到,但圖形的全集位于matplotlib.patches。
想在圖表中添加圖形時(shí),你需要生成patch(補(bǔ)丁)對象shp,并調(diào)用ax.add_patch(shp)將它加入到子圖中(參考圖12):
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
rect = plt.Rectangle((0.2, 0.75), 0.4, 0.15, color='k', alpha=0.3)
circ = plt.Circle((0.7, 0.2), 0.15, color='b', alpha=0.3)
pgon = plt.Polygon([[0.15, 0.15], [0.35, 0.4], [0.2, 0.6]],
color='g', alpha=0.5)
ax.add_patch(rect)
ax.add_patch(circ)
ax.add_patch(pgon)

▲圖12 三種個(gè)不同patch圖形的可視化
當(dāng)你看到很多常見繪圖類型的實(shí)現(xiàn)時(shí),你會(huì)發(fā)現(xiàn)他們都是從patches中組裝而來。
將圖片保存到文件
你可以使用plt.savefig將活動(dòng)圖片保存到文件。這個(gè)方法等價(jià)于圖片對象的savefig實(shí)例方法。例如將圖片保存為SVG,你只需要輸入以下代碼:
plt.savefig('figpath.svg')
文件類型是從文件擴(kuò)展名中推斷出來的。所以如果你使用.pdf,則會(huì)得到一個(gè)PDF。我常常使用幾個(gè)重要的選項(xiàng)來發(fā)布圖形:dpi,它控制每英寸點(diǎn)數(shù)的分辨率; bbox_inches,可以修剪實(shí)際圖形的空白。為了得到同樣一個(gè)PNG圖片,且使用最小的空白,擁有400 DPI,你需要運(yùn)行以下代碼:
plt.savefig('figpath.png', dpi=400, bbox_inches='tight')
savefig并一定是寫到硬盤的,它可以將圖片寫入到所有的文件型對象中,例如BytesIO:
from io import BytesIO
buffer = BytesIO()
plt.savefig(buffer)
plot_data = buffer.getvalue()
表2是savefig其他選項(xiàng)的列表:
| 參數(shù) | 描述 |
|---|---|
| fname | 包含文件路徑或Python文件型對象的字符串。圖片格式是從文件擴(kuò)展名中推斷出來的(例如PDF格式的.pdf或PNG的.png格式) |
| dpi | 每英寸點(diǎn)數(shù)的分辨率; 默認(rèn)為100,但可以配置 |
| facecolor,edgecolor | 子圖之外的圖形背景的顏色;默認(rèn)情況下是'w'(白色) |
| format | 文件格式( ('png', 'pdf', 'svg', 'ps', 'eps', … ) |
| bbox_inches | 要保存的圖片范圍;如果傳遞'pass',將會(huì)去除掉圖片周圍空白的部分 |
▲表2 Figure.savefig選項(xiàng)
matplotlib設(shè)置
matplotlib配置了配色方案和默認(rèn)設(shè)置,主要用來準(zhǔn)備用于發(fā)布的圖片。幸運(yùn)的是,幾乎所有的默認(rèn)行為都可以通過廣泛的全局參數(shù)來定制,包括圖形大小、子圖間距、顏色、字體大小和網(wǎng)格樣式等等。使用rc方法是使用Python編程修改配置的一種方式; 例如,要將全局默認(rèn)數(shù)字大小設(shè)置為10×10,你可以輸入:
plt.rc('figure', figsize=(10, 10))
rc的第一個(gè)參數(shù)是你想要自定義的組件,比如'figure'、'axes'、'xtick'、'ytick'、'grid'、'legend'等等。之后,可以按照關(guān)鍵字參數(shù)的序列指定新參數(shù)。字典是一種在程序中設(shè)置選項(xiàng)的簡單方式:
font_options = {'family' : 'monospace',
'weight' : 'bold',
'size' : 'small'}
plt.rc('font', **font_options)
如果需要更深入的定制和參看全量選項(xiàng),可以參考matplotlib的設(shè)置文件matplotlibrc,該文件位于matplotlib/mpl-data路徑。如果你定制了這個(gè)文件,并將他放置在home路徑下并且文件名為.matplotlibrc,則每次你使用matplotlib時(shí)都會(huì)讀取該文件。
關(guān)于作者:韋斯·麥金尼(Wes McKinney)是流行的Python開源數(shù)據(jù)分析庫pandas的創(chuàng)始人。他是一名活躍的演講者,也是Python數(shù)據(jù)社區(qū)和Apache軟件基金會(huì)的Python/C++開源開發(fā)者。目前他在紐約從事軟件架構(gòu)師工作。
本文摘編自《利用Python進(jìn)行數(shù)據(jù)分析》(原書第2版),經(jīng)出版方授權(quán)發(fā)布。
贈(zèng)書福利
書籍贊助方:機(jī)械工業(yè)出版社華章公司
贈(zèng)書書籍:《利用Python進(jìn)行數(shù)據(jù)分析》
贈(zèng)書規(guī)則:為本文「點(diǎn)贊」+ 「在看」 +「轉(zhuǎn)發(fā)本文至朋友圈」+「留言」,與文章內(nèi)容相關(guān)的優(yōu)質(zhì)留言即可上墻并從所有留言中隨機(jī)選出2位走心讀者留言將各獲得一本。
截止時(shí)間:2021年6月16日,晚 20:00
領(lǐng)書須知:提供轉(zhuǎn)發(fā)截圖 + 點(diǎn)贊和在看截圖
注意事項(xiàng):最終獲贈(zèng)者請?jiān)?4小時(shí)以內(nèi)添加我的微信,備注:贈(zèng)書??
推薦閱讀
杰哥的另一個(gè)公眾號(hào),主要分享關(guān)于個(gè)人成長經(jīng)歷的那點(diǎn)事,歡迎您的關(guān)注。

