參考datawhale:https://datawhalechina.github.io/joyful-pandas/build/html/%E7%9B%AE%E5%BD%95/ch4.html#id2
In [1]: import numpy as np
In [2]: import pandas as pd
一、分組模式及其對(duì)象
- 分組的一般模式
分組操作在日常生活中使用極其廣泛,例如:
依據(jù) 性別 分組,統(tǒng)計(jì)全國(guó)人口 壽命 的 平均值
依據(jù) 季節(jié) 分組,對(duì)每一個(gè)季節(jié)的 溫度 進(jìn)行 組內(nèi)標(biāo)準(zhǔn)化
依據(jù) 班級(jí) 分組,篩選出組內(nèi) 數(shù)學(xué)分?jǐn)?shù) 的 平均值超過(guò)80分的班級(jí)
從上述的幾個(gè)例子中不難看出,想要實(shí)現(xiàn)分組操作,必須明確三個(gè)要素:分組依據(jù) 、 數(shù)據(jù)來(lái)源 、 操作及其返回結(jié)果 。同時(shí)從充分性的角度來(lái)說(shuō),如果明確了這三方面,就能確定一個(gè)分組操作,從而分組代碼的一般模式即:
df.groupby(分組依據(jù))[數(shù)據(jù)來(lái)源].使用操作
例如第一個(gè)例子中的代碼就應(yīng)該如下:
df.groupby('Gender')['Longevity'].mean()
現(xiàn)在返回到學(xué)生體測(cè)的數(shù)據(jù)集上,如果想要按照性別統(tǒng)計(jì)身高中位數(shù),就可以如下寫出:
In [3]: df = pd.read_csv('data/learn_pandas.csv')
In [4]: df.groupby('Gender')['Height'].median()
Out[4]:
Gender
Female 159.6
Male 173.4
Name: Height, dtype: float64
- 分組依據(jù)的本質(zhì)
前面提到的若干例子都是以單一維度進(jìn)行分組的,比如根據(jù)性別,如果現(xiàn)在需要根據(jù)多個(gè)維度進(jìn)行分組,該如何做?事實(shí)上,只需在 groupby 中傳入相應(yīng)列名構(gòu)成的列表即可。例如,現(xiàn)希望根據(jù)學(xué)校和性別進(jìn)行分組,統(tǒng)計(jì)身高的均值就可以如下寫出:
In [5]: df.groupby(['School', 'Gender'])['Height'].mean()
Out[5]:
School Gender
Fudan University Female 158.776923
Male 174.212500
Peking University Female 158.666667
Male 172.030000
Shanghai Jiao Tong University Female 159.122500
Male 176.760000
Tsinghua University Female 159.753333
Male 171.638889
Name: Height, dtype: float64
目前為止, groupby 的分組依據(jù)都是直接可以從列中按照名字獲取的,那如果希望通過(guò)一定的復(fù)雜邏輯來(lái)分組,例如根據(jù)學(xué)生體重是否超過(guò)總體均值來(lái)分組,同樣還是計(jì)算身高的均值。
首先應(yīng)該先寫出分組條件:
In [6]: condition = df.Weight > df.Weight.mean()
然后將其傳入 groupby 中:
In [7]: df.groupby(condition)['Height'].mean()
Out[7]:
Weight
False 159.034646
True 172.705357
Name: Height, dtype: float64
從索引可以看出,其實(shí)最后產(chǎn)生的結(jié)果就是按照條件列表中元素的值(此處是 True 和 False )來(lái)分組,下面用隨機(jī)傳入字母序列來(lái)驗(yàn)證這一想法:
In [8]: item = np.random.choice(list('abc'), df.shape[0])
In [9]: df.groupby(item)['Height'].mean()
Out[9]:
a 163.924242
b 162.928814
c 162.708621
Name: Height, dtype: float64
此處的索引就是原先item中的元素,如果傳入多個(gè)序列進(jìn)入 groupby ,那么最后分組的依據(jù)就是這兩個(gè)序列對(duì)應(yīng)行的唯一組合:
In [10]: df.groupby([condition, item])['Height'].mean()
Out[10]:
Weight
False a 160.193617
b 158.921951
c 157.756410
True a 173.152632
b 172.055556
c 172.873684
Name: Height, dtype: float64
由此可以看出,之前傳入列名只是一種簡(jiǎn)便的記號(hào),事實(shí)上等價(jià)于傳入的是一個(gè)或多個(gè)列,最后分組的依據(jù)來(lái)自于數(shù)據(jù)來(lái)源組合的unique值,通過(guò) drop_duplicates 就能知道具體的組類別:
In [11]: df[['School', 'Gender']].drop_duplicates()
Out[11]:
School Gender
0 Shanghai Jiao Tong University Female
1 Peking University Male
2 Shanghai Jiao Tong University Male
3 Fudan University Female
4 Fudan University Male
5 Tsinghua University Female
9 Peking University Female
16 Tsinghua University Male
In [12]: df.groupby([df['School'], df['Gender']])['Height'].mean()
Out[12]:
School Gender
Fudan University Female 158.776923
Male 174.212500
Peking University Female 158.666667
Male 172.030000
Shanghai Jiao Tong University Female 159.122500
Male 176.760000
Tsinghua University Female 159.753333
Male 171.638889
Name: Height, dtype: float64
- Groupby對(duì)象
能夠注意到,最終具體做分組操作時(shí),所調(diào)用的方法都來(lái)自于 pandas 中的 groupby 對(duì)象,這個(gè)對(duì)象上定義了許多方法,也具有一些方便的屬性。
In [13]: gb = df.groupby(['School', 'Grade'])
In [14]: gb
Out[14]: <pandas.core.groupby.generic.DataFrameGroupBy object at 0x0000024372714408>
通過(guò) ngroups 屬性,可以得到分組個(gè)數(shù):
In [15]: gb.ngroups
Out[15]: 16
通過(guò) groups 屬性,可以返回從 組名 映射到 組索引列表 的字典:
In [16]: res = gb.groups
In [17]: res.keys() # 字典的值由于是索引,元素個(gè)數(shù)過(guò)多,此處只展示字典的鍵
Out[17]: dict_keys([('Fudan University', 'Freshman'), ('Fudan University', 'Junior'), ('Fudan University', 'Senior'), ('Fudan University', 'Sophomore'), ('Peking University', 'Freshman'), ('Peking University', 'Junior'), ('Peking University', 'Senior'), ('Peking University', 'Sophomore'), ('Shanghai Jiao Tong University', 'Freshman'), ('Shanghai Jiao Tong University', 'Junior'), ('Shanghai Jiao Tong University', 'Senior'), ('Shanghai Jiao Tong University', 'Sophomore'), ('Tsinghua University', 'Freshman'), ('Tsinghua University', 'Junior'), ('Tsinghua University', 'Senior'), ('Tsinghua University', 'Sophomore')])
當(dāng) size 作為 DataFrame 的屬性時(shí),返回的是表長(zhǎng)乘以表寬的大小,但在 groupby 對(duì)象上表示統(tǒng)計(jì)每個(gè)組的元素個(gè)數(shù):
In [18]: gb.size()
Out[18]:
School Grade
Fudan University Freshman 9
Junior 12
Senior 11
Sophomore 8
Peking University Freshman 13
Junior 8
Senior 8
Sophomore 5
Shanghai Jiao Tong University Freshman 13
Junior 17
Senior 22
Sophomore 5
Tsinghua University Freshman 17
Junior 22
Senior 14
Sophomore 16
dtype: int64
通過(guò) get_group 方法可以直接獲取所在組對(duì)應(yīng)的行,此時(shí)必須知道組的具體名字:
In [19]: gb.get_group(('Fudan University', 'Freshman')).iloc[:3, :3] # 展示一部分
Out[19]:
School Grade Name
15 Fudan University Freshman Changqiang Yang
28 Fudan University Freshman Gaoqiang Qin
63 Fudan University Freshman Gaofeng Zhao
這里列出了2個(gè)屬性和2個(gè)方法,而先前的 mean 、 median 都是 groupby 對(duì)象上的方法,這些函數(shù)和許多其他函數(shù)的操作具有高度相似性,將在之后的小節(jié)進(jìn)行專門介紹。
-
分組的三大操作
熟悉了一些分組的基本知識(shí)后,重新回到開(kāi)頭舉的三個(gè)例子,可能會(huì)發(fā)現(xiàn)一些端倪,即這三種類型分組返回的數(shù)據(jù)型態(tài)并不一樣:第一個(gè)例子中,每一個(gè)組返回一個(gè)標(biāo)量值,可以是平均值、中位數(shù)、組容量 size 等
第二個(gè)例子中,做了原序列的標(biāo)準(zhǔn)化處理,也就是說(shuō)每組返回的是一個(gè) Series 類型
第三個(gè)例子中,既不是標(biāo)量也不是序列,返回的整個(gè)組所在行的本身,即返回了 DataFrame 類型
由此,引申出分組的三大操作:聚合、變換和過(guò)濾,分別對(duì)應(yīng)了三個(gè)例子的操作,下面就要分別介紹相應(yīng)的 agg 、 transform 和 filter 函數(shù)及其操作。
二、聚合函數(shù)
1. 內(nèi)置聚合函數(shù)
在介紹agg之前,首先要了解一些直接定義在groupby對(duì)象的聚合函數(shù),因?yàn)樗乃俣然径紩?huì)經(jīng)過(guò)內(nèi)部的優(yōu)化,使用功能時(shí)應(yīng)當(dāng)優(yōu)先考慮。根據(jù)返回標(biāo)量值的原則,包括如下函數(shù): max/min/mean/median/count/all/any/idxmax/idxmin/mad/nunique/skew/quantile/sum/std/var/sem/size/prod` 。
In [20]: gb = df.groupby('Gender')['Height']
In [21]: gb.idxmin()
Out[21]:
Gender
Female 143
Male 199
Name: Height, dtype: int64
In [22]: gb.quantile(0.95)
Out[22]:
Gender
Female 166.8
Male 185.9
Name: Height, dtype: float64
這些聚合函數(shù)當(dāng)傳入的數(shù)據(jù)來(lái)源包含多個(gè)列時(shí),將按照列進(jìn)行迭代計(jì)算:
In [23]: gb = df.groupby('Gender')[['Height', 'Weight']]
In [24]: gb.max()
Out[24]:
Height Weight
Gender
Female 170.2 63.0
Male 193.9 89.0
-
agg方法
雖然在 groupby 對(duì)象上定義了許多方便的函數(shù),但仍然有以下不便之處:無(wú)法同時(shí)使用多個(gè)函數(shù)
無(wú)法對(duì)特定的列使用特定的聚合函數(shù)
無(wú)法使用自定義的聚合函數(shù)
無(wú)法直接對(duì)結(jié)果的列名在聚合前進(jìn)行自定義命名
下面說(shuō)明如何通過(guò) agg 函數(shù)解決這四類問(wèn)題:
【a】使用多個(gè)函數(shù)
當(dāng)使用多個(gè)聚合函數(shù)時(shí),需要用列表的形式把內(nèi)置聚合函數(shù)對(duì)應(yīng)的字符串傳入,先前提到的所有字符串都是合法的。
In [25]: gb.agg(['sum', 'idxmax', 'skew'])
Out[25]:
Height Weight
sum idxmax skew sum idxmax skew
Gender
Female 21014.0 28 -0.219253 6469.0 28 -0.268482
Male 8854.9 193 0.437535 3929.0 2 -0.332393
從結(jié)果看,此時(shí)的列索引為多級(jí)索引,第一層為數(shù)據(jù)源,第二層為使用的聚合方法,分別逐一對(duì)列使用聚合,因此結(jié)果為6列。
【b】對(duì)特定的列使用特定的聚合函數(shù)
對(duì)于方法和列的特殊對(duì)應(yīng),可以通過(guò)構(gòu)造字典傳入 agg 中實(shí)現(xiàn),其中字典以列名為鍵,以聚合字符串或字符串列表為值。
In [26]: gb.agg({'Height':['mean','max'], 'Weight':'count'})
Out[26]:
Height Weight
mean max count
Gender
Female 159.19697 170.2 135
Male 173.62549 193.9 54
【c】使用自定義函數(shù)
在 agg 中可以使用具體的自定義函數(shù), 需要注意傳入函數(shù)的參數(shù)是之前數(shù)據(jù)源中的列,逐列進(jìn)行計(jì)算 。下面分組計(jì)算身高和體重的極差:
In [27]: gb.agg(lambda x: x.mean()-x.min())
Out[27]:
Height Weight
Gender
Female 13.79697 13.918519
Male 17.92549 21.759259
由于傳入的是序列,因此序列上的方法和屬性都是可以在函數(shù)中使用的,只需保證返回值是標(biāo)量即可。下面的例子是指,如果組的指標(biāo)均值,超過(guò)該指標(biāo)的總體均值,返回High,否則返回Low。
In [28]: def my_func(s):
....: res = 'High'
....: if s.mean() <= df[s.name].mean():
....: res = 'Low'
....: return res
....:
In [29]: gb.agg(my_func)
Out[29]:
Height Weight
Gender
Female Low Low
Male High High
【d】聚合結(jié)果重命名
如果想要對(duì)聚合結(jié)果的列名進(jìn)行重命名,只需要將上述函數(shù)的位置改寫成元組,元組的第一個(gè)元素為新的名字,第二個(gè)位置為原來(lái)的函數(shù),包括聚合字符串和自定義函數(shù),現(xiàn)舉若干例子說(shuō)明:
In [30]: gb.agg([('range', lambda x: x.max()-x.min()), ('my_sum', 'sum')])
Out[30]:
Height Weight
range my_sum range my_sum
Gender
Female 24.8 21014.0 29.0 6469.0
Male 38.2 8854.9 38.0 3929.0
In [31]: gb.agg({'Height': [('my_func', my_func), 'sum'],
....: 'Weight': lambda x:x.max()})
....:
Out[31]:
Height Weight
my_func sum <lambda>
Gender
Female Low 21014.0 63.0
Male High 8854.9 89.0
另外需要注意,使用對(duì)一個(gè)或者多個(gè)列使用單個(gè)聚合的時(shí)候,重命名需要加方括號(hào),否則就不知道是新的名字還是手誤輸錯(cuò)的內(nèi)置函數(shù)字符串:
In [32]: gb.agg([('my_sum', 'sum')])
Out[32]:
Height Weight
my_sum my_sum
Gender
Female 21014.0 6469.0
Male 8854.9 3929.0
In [33]: gb.agg({'Height': [('my_func', my_func), 'sum'],
....: 'Weight': [('range', lambda x:x.max())]})
....:
Out[33]:
Height Weight
my_func sum range
Gender
Female Low 21014.0 63.0
Male High 8854.9 89.0
三、變換和過(guò)濾
1. 變換函數(shù)與transform方法
變換函數(shù)的返回值為同長(zhǎng)度的序列,最常用的內(nèi)置變換函數(shù)是累計(jì)函數(shù): cumcount/cumsum/cumprod/cummax/cummin ,它們的使用方式和聚合函數(shù)類似,只不過(guò)完成的是組內(nèi)累計(jì)操作。此外在 groupby 對(duì)象上還定義了填充類和滑窗類的變換函數(shù).
In [34]: gb.cummax().head()
Out[34]:
Height Weight
0 158.9 46.0
1 166.5 70.0
2 188.9 89.0
3 NaN 46.0
4 188.9 89.0
當(dāng)用自定義變換時(shí)需要使用 transform 方法,被調(diào)用的自定義函數(shù), 其傳入值為數(shù)據(jù)源的序列 ,與 agg 的傳入類型是一致的,其最后的返回結(jié)果是行列索引與數(shù)據(jù)源一致的 DataFrame 。
現(xiàn)對(duì)身高和體重進(jìn)行分組標(biāo)準(zhǔn)化,即減去組均值后除以組的標(biāo)準(zhǔn)差:
In [35]: gb.transform(lambda x: (x-x.mean())/x.std()).head()
Out[35]:
Height Weight
0 -0.058760 -0.354888
1 -1.010925 -0.355000
2 2.167063 2.089498
3 NaN -1.279789
4 0.053133 0.159631
前面提到了 transform 只能返回同長(zhǎng)度的序列,但事實(shí)上還可以返回一個(gè)標(biāo)量,這會(huì)使得結(jié)果被廣播到其所在的整個(gè)組,這種 標(biāo)量廣播 的技巧在特征工程中是非常常見(jiàn)的。例如,構(gòu)造兩列新特征來(lái)分別表示樣本所在性別組的身高均值和體重均值:
In [36]: gb.transform('mean').head() # 傳入返回標(biāo)量的函數(shù)也是可以的
Out[36]:
Height Weight
0 159.19697 47.918519
1 173.62549 72.759259
2 173.62549 72.759259
3 159.19697 47.918519
4 173.62549 72.759259
- 組索引與過(guò)濾
在上一章中介紹了索引的用法,那么索引和過(guò)濾有什么區(qū)別呢?
過(guò)濾在分組中是對(duì)于組的過(guò)濾,而索引是對(duì)于行的過(guò)濾,在第二章中的返回值,無(wú)論是布爾列表還是元素列表或者位置列表,本質(zhì)上都是對(duì)于行的篩選,即如果符合篩選條件的則選入結(jié)果表,否則不選入。
組過(guò)濾作為行過(guò)濾的推廣,指的是如果對(duì)一個(gè)組的全體所在行進(jìn)行統(tǒng)計(jì)的結(jié)果返回 True 則會(huì)被保留, False 則該組會(huì)被過(guò)濾,最后把所有未被過(guò)濾的組其對(duì)應(yīng)的所在行拼接起來(lái)作為 DataFrame 返回。
在 groupby 對(duì)象中,定義了 filter 方法進(jìn)行組的篩選,其中自定義函數(shù)的輸入?yún)?shù)為數(shù)據(jù)源構(gòu)成的 DataFrame 本身,在之前例子中定義的 groupby 對(duì)象中,傳入的就是 df[['Height', 'Weight']] ,因此所有表方法和屬性都可以在自定義函數(shù)中相應(yīng)地使用,同時(shí)只需保證自定義函數(shù)的返回為布爾值即可。
例如,在原表中通過(guò)過(guò)濾得到所有容量大于100的組:
In [37]: gb.filter(lambda x: x.shape[0] > 100).head()
Out[37]:
Height Weight
0 158.9 46.0
3 NaN 41.0
5 158.0 51.0
6 162.5 52.0
7 161.9 50.0
四、跨列分組
- apply的引入
之前幾節(jié)介紹了三大分組操作,但事實(shí)上還有一種常見(jiàn)的分組場(chǎng)景,無(wú)法用前面介紹的任何一種方法處理,例如現(xiàn)在如下定義身體質(zhì)量指數(shù)BMI:
BMI=Weight/Height**2
其中體重和身高的單位分別為千克和米,需要分組計(jì)算組BMI的均值。
首先,這顯然不是過(guò)濾操作,因此 filter 不符合要求;其次,返回的均值是標(biāo)量而不是序列,因此 transform 不符合要求;最后,似乎使用 agg 函數(shù)能夠處理,但是之前強(qiáng)調(diào)過(guò)聚合函數(shù)是逐列處理的,而不能夠 多列數(shù)據(jù)同時(shí)處理 。由此,引出了 apply 函數(shù)來(lái)解決這一問(wèn)題。
- apply的使用
在設(shè)計(jì)上, apply 的自定義函數(shù)傳入?yún)?shù)與 filter 完全一致,只不過(guò)后者只允許返回布爾值?,F(xiàn)如下解決上述計(jì)算問(wèn)題:
In [38]: def BMI(x):
....: Height = x['Height']/100
....: Weight = x['Weight']
....: BMI_value = Weight/Height**2
....: return BMI_value.mean()
....:
In [39]: gb.apply(BMI)
Out[39]:
Gender
Female 18.860930
Male 24.318654
dtype: float64
除了返回標(biāo)量之外, apply 方法還可以返回一維 Series 和二維 DataFrame ,但它們產(chǎn)生的數(shù)據(jù)框維數(shù)和多級(jí)索引的層數(shù)應(yīng)當(dāng)如何變化?下面舉三組例子就非常容易明白結(jié)果是如何生成的:
【a】標(biāo)量情況:結(jié)果得到的是 Series ,索引與 agg 的結(jié)果一致
In [40]: gb = df.groupby(['Gender','Test_Number'])[['Height','Weight']]
In [41]: gb.apply(lambda x: 0)
Out[41]:
Gender Test_Number
Female 1 0
2 0
3 0
Male 1 0
2 0
3 0
dtype: int64
In [42]: gb.apply(lambda x: [0, 0]) # 雖然是列表,但是作為返回值仍然看作標(biāo)量
Out[42]:
Gender Test_Number
Female 1 [0, 0]
2 [0, 0]
3 [0, 0]
Male 1 [0, 0]
2 [0, 0]
3 [0, 0]
dtype: object
【b】 Series 情況:得到的是 DataFrame ,行索引與標(biāo)量情況一致,列索引為 Series 的索引
In [43]: gb.apply(lambda x: pd.Series([0,0],index=['a','b']))
Out[43]:
a b
Gender Test_Number
Female 1 0 0
2 0 0
3 0 0
Male 1 0 0
2 0 0
3 0 0
【c】 DataFrame 情況:得到的是 DataFrame ,行索引最內(nèi)層在每個(gè)組原先 agg 的結(jié)果索引上,再加一層返回的 DataFrame 行索引,同時(shí)分組結(jié)果 DataFrame 的列索引和返回的 DataFrame 列索引一致。
In [44]: gb.apply(lambda x: pd.DataFrame(np.ones((2,2)),
....: index = ['a','b'],
....: columns=pd.Index([('w','x'),('y','z')])))
....:
Out[44]:
w y
x z
Gender Test_Number
Female 1 a 1.0 1.0
b 1.0 1.0
2 a 1.0 1.0
b 1.0 1.0
3 a 1.0 1.0
b 1.0 1.0
Male 1 a 1.0 1.0
b 1.0 1.0
2 a 1.0 1.0
b 1.0 1.0
3 a 1.0 1.0
b 1.0 1.0
最后需要強(qiáng)調(diào)的是, apply 函數(shù)的靈活性是以犧牲一定性能為代價(jià)換得的,除非需要使用跨列處理的分組處理,否則應(yīng)當(dāng)使用其他專門設(shè)計(jì)的 groupby 對(duì)象方法,否則在性能上會(huì)存在較大的差距。同時(shí),在使用聚合函數(shù)和變換函數(shù)時(shí),也應(yīng)當(dāng)優(yōu)先使用內(nèi)置函數(shù),它們經(jīng)過(guò)了高度的性能優(yōu)化,一般而言在速度上都會(huì)快于用自定義函數(shù)來(lái)實(shí)現(xiàn)。
五.總結(jié)
這章屬于重點(diǎn)章節(jié),分組聚合在工程中運(yùn)用甚廣,做挖掘的時(shí)候常常用到這部分內(nèi)容,學(xué)習(xí)之前,一直認(rèn)為agg只能對(duì)python的某些內(nèi)置函數(shù)進(jìn)行聚合,分不清transform和apply的一些區(qū)別,apply比transform來(lái)說(shuō)更加靈活,而且在面對(duì)復(fù)雜計(jì)算的時(shí)候,我們可以考慮使用apply和transform結(jié)合的方法來(lái)做,這樣做的效率也比單一使用的時(shí)候大大提升了。再說(shuō)一下在之前的學(xué)習(xí)中用分組聚合遇到的坑,其中一個(gè)是對(duì)某一列進(jìn)行分組聚合的時(shí)候,由于我要對(duì)這一列進(jìn)行歸一化處理,所以我之前錯(cuò)誤的寫法是
df['b'].apply(lambda x:(x-x.min())/(x.max()-x.min()))
而正確的寫法是:
df[['b']].apply(lambda x:(x-x.min())/(x.max()-x.min()))
倆者的區(qū)別是前一種寫法是值的計(jì)算,而后一種寫法是列的計(jì)算,這里是初學(xué)者特別容易犯的錯(cuò)誤,需要注意。
還有reset_index()的使用,比如什么時(shí)候應(yīng)該指定drop=True,而什么時(shí)候不需要指定。
比如:
df.groupby('a').apply(lambda x:test(x)).reset_index(drop=True)
def test(df):
return df[:-1]
這種情況就需要指定drop=True,個(gè)人理解是分組切的時(shí)候沒(méi)有改變?cè)瓉?lái)相對(duì)的索引,所以需要將分組之后的相對(duì)索引干掉。
而這種情況則不需要去掉:
df.groupby('a')[['b','c']].count().reset_index()
這種情況沒(méi)有保留原來(lái)的相對(duì)索引,而是把分組的那一列作為了新索引,如果我們?cè)趓eset_index()的時(shí)候指定drop=True,那么就會(huì)刪除這一列。
坑就先說(shuō)到這里,還有一些小坑就不再這里列舉了,希望大家平時(shí)勤做筆記,將遇到的問(wèn)題記錄下來(lái),方便之后遇到同樣的問(wèn)題,不需要再耗費(fèi)大量的時(shí)間,最后祝大家節(jié)日快樂(lè)!