Python3基本工具包:Pandas(2)

作者:xxw9485
時間:2018/3/10
來源:http://mp.weixin.qq.com/s/pm8503plIouWGAtS3zAM5Q


2、數據框

作爲從事數據相關工作的我們,平時接觸的更多的是一張有板有眼的數據表格,在這裏我們就叫作數據框。在Python中可以通過pandas模塊的DataFrame函數構造數據框。

2.1 數據框的構造

2.1.1 通過列表創建數據框

這種創建數據框的方式,默認沒有列名稱的,不過可以運用DataFrame函數中的columns參數給數據框的每列添加名稱。如果你需要給行加上索引名稱,你可以使用index參數。

# 輸入:
# 構造數據框
import pandas as pd
a = pd.DataFrame([[1,2,3],[10,20,30],[100,200,300],[1,10,100]])
print(a,'\n')
b = pd.DataFrame([[1,2,3],[10,20,30],[100,200,300],[1,10,100]],columns=['v1','v2','v3']) # 添加列名稱
print(b)
# 輸出:
     0    1    2
0    1    2    3
1   10   20   30
2  100  200  300
3    1   10  100

    v1   v2   v3
0    1    2    3
1   10   20   30
2  100  200  300
3    1   10  100

2.1.2 通過字典創建數據框

這種創建數據框的方式,輸出結果中列名稱順序與構造時的數據不一致,這是因爲字典並非是一種序列,而是一種特殊的鍵值對關係的對象。如果你需要按照指定的列順序排列,仍然可以通過columns參數實現。

# 輸入:
import pandas as pd
a = pd.DataFrame({'id':[1,2,3],'name':['Tom','Lily','Jim'],'age':[20,21,22]})
print(a,'\n')
b = pd.DataFrame({'id':[1,2,3],'name':['Tom','Lily','Jim'],'age':[20,21,22]},columns=['id','name','age'])
print(b)
# 輸出:
   age  id  name
0   20   1   Tom
1   21   2  Lily
2   22   3   Jim 

   id  name  age
0   1   Tom   20
1   2  Lily   21
2   3   Jim   22

2.2 數據的讀入

2.2.1 文本文件的讀取

在pandas模塊中有read_table和read_csv兩個函數讀取常見的文本文件。read_table和read_csv兩個函數都可以讀文本文件數據,區別在於默認的sep參數不一致,read_table默認以製表符Tab鍵爲字段間的間隔符,而read_csv默認以逗號爲字段間的間隔符。

# 輸入:
import pandas as pd
books = pd.read_table('book.csv',sep=',',header=None,usecols=[0,1,3],names=['type','title','author'])
print(books.tail(),'\n') # 默認輸出最後5行
print(books.tail(1),'\n') # 輸出最後1行
print(books.head(),'\n') # 默認輸出前5行
print(books.head(1)) # 輸出前1行
# 輸出:
   type     title author
5  spss  spss2015     小明
6  spss  spss2016     小明
7  spss  spss2017     小明
8  spss  spss2018     小明
9  spss  spss2019     小明 

   type     title author
9  spss  spss2019     小明

   type     title author
0  spss  spss2010     小明
1  spss  spss2011     小明
2  spss  spss2012     小明
3  spss  spss2013     小明
4  spss  spss2014     小明 

   type     title author
0  spss  spss2010     小明

由於原始數據文件books.txt沒有字段名稱,故設置header=None,並用names參數給表字段加上名稱,usecols則是設置讀取原始數據的哪些列。

2.2.2 電子表格的讀取

pandas模塊中read_excel函數可以非常方便的讀取外部的xls和xlsx電子表格:

# 輸入:
import pandas as pd
a = pd.read_excel(r'D:\Python36\test2018.3.19\test.xlsx',header=None)
print(a.head()) # 數據集的前五行
# 輸出:
    0                  1       2     3          4
0  上海     紐海信息技術(上海)有限公司    8581   1號店    2000人以上
1  上海   上海點榮金融信息服務有限責任公司   23177   點融網  500-20002  上海     上海晶樵網絡信息技術有限公司   57561   SPD    50-1503  上海  杭州數雲信息技術有限公司上海分公司    7502    數雲   150-5004  上海     上海銀基富力信息技術有限公司  130876  銀基富力     15-50

2.2.3 MySQL數據庫數據的讀取

使用Python讀取MySQL數據庫,還需要結合pymysql模塊一起使用。
在MySQL中創建數據:

# 建庫
create database test;
# 調用庫名稱
use test;
# 創建表
create table user_info(
id int,
name varchar(10),
gender varchar(2),
age tinyint,
income smallint);
# 賦值
insert into user_info values
(1,'Tom','M',28,15000),
(2,'Lily','F',27,17000),
(3,'Lucy','F',37,15600),
(4,'Jim','M',29,20000),
運用Python與MySQL創建連接,並讀取數據:
import pymysql 
import pandas as pd
# 創建連接
conn = pymysql.connect(host='localhost',port=3306,user='root',password='123456',database='test',charset='utf8')
user_info = pd.read_sql('select * from user_info',conn) # 讀取數據
print(user_info)
# 關閉連接
conn.close() 

2.3 數據的概覽信息

  • shape屬性和columns屬性返回數據集的行列數及變量名;
  • describe屬性可以對數值型變量(include=[‘number’])和離散型變量(include=[‘object’])進行描述性統計;
  • info屬性則對數據集的變量類型進行簡單的描述。

2.4 數據篩選

在pandas取出一列有兩種方法,一種是比較普遍適用的名稱索引法,另一種則是點取法。

# 輸入:
import pandas as pd
a = pd.read_excel(r'D:\Python36\test2018.3.19\test.xlsx')
print(a.head(1),'\n') # 數據集的前1行
print(a['city'].head()) #名稱索引法取出某列數據
#print(a.city.head()) #點取法取出某列數據,結果同上
# 輸出:
  city            company  number  name     people
0   上海     紐海信息技術(上海)有限公司    8581   1號店    2000人以上

0    上海
1    上海
2    上海
3    上海
4    上海
Name: city, dtype: object

如果使用點取法取出數據集中的某列,需要注意的是列的名稱必須是一個整體,例如stu age或stu.age等格式的變量名就不能使用點取法。
如果你需要取出多列數據時,那不管是Python還是R語言只能使用名稱索引或位置索引了。

  • 一個變量的觀測篩選:
# 輸入:
print(a.loc[a.people=='2000人以上',:].head())
# 輸出:
  city         company  number            name   people
0   上海  紐海信息技術(上海)有限公司    8581             1號店  2000人以上
7   上海  上海安碩信息技術股份有限公司   21863  安碩信息(amarsoft)  2000人以上
  • 兩個變量的觀測篩選:
# 輸入:
print(a.loc[(a.people=='2000人以上')&(a.name=='1號店'),:])
# 輸出:
  city         company  number name   people
0   上海  紐海信息技術(上海)有限公司    8581  1號店  2000人以上

需要注意的是:多個變量的篩選,可以是或(|)關係、可以是且(&)關係還可以是非(~)關係,一定要用圓括號把條件括起來。

  • 兩個變量的觀測篩選並篩選部分變量:
# 輸入:
print(a.loc[(a.people=='2000人以上')&(a.name=='1號店'),['city','company']])
# 輸出:
  city         company
0   上海  紐海信息技術(上海)有限公司

2.5 變量的刪除

有時,在一張表裏你可能需要刪除與建模或分析無關緊要的變量,如用戶id、姓名、郵編號碼等。在Python中,你可以藉助於drop函數非常輕鬆的刪除指定的變量。

# 輸入:
print(a.drop(['number'], axis = 1).head(1))
# 輸出:
  city            company  name     people
0   上海     紐海信息技術(上海)有限公司   1號店    2000人以上

注意:該函數默認的axis=0,表示刪除行觀測,如果需要刪除列,就要將axis設置爲1。記住,此時雖然刪除了兩個變量,但數據集本身是沒有變化的,如果你需要改變數據集,需要設置inplace爲True。

2.6 變量重命名

需要更換變量名時,rename函數可以幫助我們解決問題:

# 輸入:
print(a.rename(columns={'city':'城市'}).head(1))
# 輸出:
   城市         company  number name   people
0  上海  紐海信息技術(上海)有限公司    8581  1號店  2000人以上

2.7 數據類型轉化

字符型數值轉數值:可以通過astype函數把字符型變量轉化爲整數型和浮點型。
實例:

# 輸入
print(a.dtypes)
a = a.astype({'number':'object'})
print(a.dtypes)
# 輸出
city       object
company    object
number      int64
name       object
people     object
dtype: object
city       object
company    object
number     object
name       object
people     object
dtype: object

2.8 數據集的排序

如果你需要對你的數據集進行排序,Python中pandas模塊也提供了非常好用的sort_values函數。

# 輸入:
print(a.sort_values(by = ['number'],ascending = [True]).head())
# 輸出:
  city            company  number            name     people
6   上海       上海好體信息科技有限公司    2002            足球魔方   150-5003   上海  杭州數雲信息技術有限公司上海分公司    7502              數雲   150-5000   上海     紐海信息技術(上海)有限公司    8581             1號店    2000人以上
7   上海     上海安碩信息技術股份有限公司   21863  安碩信息(amarsoft)    2000人以上
1   上海   上海點榮金融信息服務有限責任公司   23177             點融網  500-2000

2.9 數據去重

在數據清洗中,往往都要檢查一下數據集的觀測行是否有重複,duplicated函數可以用來檢查數據集是否重複,如果重複,則會在重複的行顯示True。然後,通過drop_duplicates函數對數據集的重複觀測進行刪除。這兩個函數均有subset參數,默認對數據集的所有變量進行重複性檢測和刪除,如果你需要指定某些變量的重複性檢查和刪除就可以往subset參數傳遞變量。

# 輸入:
import pandas as pd
data = pd.DataFrame({'name':['liu','li','chen','liu'],
                    'age':[20,21,22,20],
                    'gender':['M','M','M','M']})
print(data)
print(data.duplicated()) # 檢查數據集是否重複
print(data.drop_duplicates()) # 刪除重複觀測
print(data.duplicated(subset='gender')) # 指定檢測某個變量是否重複
# 輸出:
   age gender  name
0   20      M   liu
1   21      M    li
2   22      M  chen
3   20      M   liu
0    False
1    False
2    False
3     True
dtype: bool
   age gender  name
0   20      M   liu
1   21      M    li
2   22      M  chen
0    False
1     True
2     True
3     True
dtype: bool

2.10 數據抽樣

pandas模塊有一個sample函數可以幫助我們完成抽樣的任務,語法:

sample(n = None, frac = None, replace = False, weights = None, random_state = None)
  • n:指定抽樣的個數
  • frac:指定抽樣的比例
  • replace:指定是否有放回的抽樣,默認爲無放回抽樣
  • weights:指定每個樣本被抽中的概率,默認每個樣本抽中的概率相等
  • random_state :指定抽樣的隨機種子,默認無固定的隨機種子,即每次抽樣的結果不一樣
# 輸入:
import pandas as pd
a = pd.read_excel(r'D:\Python36\test2018.3.19\test.xlsx')
train = a.sample(frac = 0.5, random_state = 1)
print(train,'\n')
test = a.loc[~a.index.isin(train.index),:] # "~"表示非
print(test)
# 輸出:
  city           company  number  name    people
2   上海    上海晶樵網絡信息技術有限公司   57561   SPD   50-1509   上海  五五海淘(上海)科技股份有限公司   58109  55海淘  150-5006   上海      上海好體信息科技有限公司    2002  足球魔方  150-5004   上海    上海銀基富力信息技術有限公司  130876  銀基富力    15-500   上海    紐海信息技術(上海)有限公司    8581   1號店   2000人以上 

  city            company  number            name     people
1   上海   上海點榮金融信息服務有限責任公司   23177             點融網  500-20003   上海  杭州數雲信息技術有限公司上海分公司    7502              數雲   150-5005   上海      上海青之桐投資管理有限公司   28095            青桐資本    50-1507   上海     上海安碩信息技術股份有限公司   21863  安碩信息(amarsoft)    2000人以上
8   上海     上海崇杏健康管理諮詢有限公司  121208            上海崇杏     15-50

訓練集可以直接從sample函數中抽取出來,測試集則通過索引的方式,將訓練集中的行號排除出去。

2.11 頻數統計

頻數統計,顧名思義就是統計某個離散變量各水平的頻次。

# 輸入:
print(a.people.value_counts(),'\n') # 統計各個people小組的人數
print(a.people.value_counts()/sum(a.people.value_counts())) # 統計各個people小組的佔比情況
# 輸出:
150-5003
2000人以上      2
50-1502
15-502
500-20001
Name: people, dtype: int64

150-5000.3
50-1500.2
15-500.2
2000人以上      0.2
500-20000.1
Name: people, dtype: float64

需要統計兩個離散變量的交叉統計表時,可以使用pandas模塊提供的crosstab函數。

# 輸入:
b = pd.crosstab(index = a.city, columns = a['people'])
print(b)
# 輸出:
people  15-50150-5002000人以上  50-150500-2000人
city                                                 
上海           2         3        2        2          1

2.12 缺失值處理

對於缺失值我們可以通過pandas模塊中的isnull函數監控每個變量是否存在缺失,缺失的比例如何,然後通過pandas模塊中的dropna函數和fillna函數進行刪除或替補處理。

  • 首先,我們手工編造一個含缺失值的數據框:
# 輸入:
import pandas as pd
import numpy as np
df = pd.DataFrame([[1,2,3,4],[np.NaN,6,7,np.NaN],[11,np.NaN,12,13],
                 [100,200,300,400],[20,40,60,np.NaN]], columns = ['x1','x2','x3','x4'])
print(df)
# 輸出:
      x1     x2   x3     x4
0    1.0    2.0    3    4.0
1    NaN    6.0    7    NaN
2   11.0    NaN   12   13.0
3  100.0  200.0  300  400.0
4   20.0   40.0   60    NaN
  • 其次,使用isnull函數檢查數據集的缺失情況:
# 輸入:
# 整個數據集是否存在缺失
print(any(df.isnull()),'\n') 
# 每一列是否有缺失、以及缺失比例
is_null = []
null_ratio = []
for col in df.columns:
    is_null.append(any(pd.isnull(df[col])))
    null_ratio.append(float(round(sum(pd.isnull(df[col]))/df.shape[0],2)))
print(is_null,'\n', null_ratio, '\n')
# 每一行是否有缺失
is_null = []
for index in list(df.index):
    is_null.append(any(pd.isnull(df.iloc[index,:])))
print(is_null,'\n')
# 輸出:
True 

[True, True, False, True] 
 [0.2, 0.2, 0.0, 0.4] 

[False, True, True, False, True] 
  • 最後,對缺失數據進行處理:
刪除法

dropna函數,有兩種刪除模式,一種是對含有缺失的行(任意一列)進行刪除,另一種是刪除那些全是缺失(所有列)的行:

# 輸入:
print(df.dropna(),'\n') # 刪除任何含有缺失的行
print(df.dropna(how = 'all')) # 刪除全是缺失的行
# 輸出:
      x1     x2   x3     x4
0    1.0    2.0    3    4.0
3  100.0  200.0  300  400.0 

      x1     x2   x3     x4
0    1.0    2.0    3    4.0
1    NaN    6.0    7    NaN
2   11.0    NaN   12   13.0
3  100.0  200.0  300  400.0
4   20.0   40.0   60    NaN
替補法

fillna函數提供前向替補、後向替補和函數替補的幾種方法:

# 輸入:
print(df.fillna(method='ffill'),'\n') # 前向替補
print(df.fillna(method='bfill'),'\n') # 後向替補
# 不同的列用不同的函數替補
print(df.fillna(value = {'x1':df.x1.mean(),
                        'x2':df.x2.median(),
                        'x4':df.x4.max()}))
# 輸出:
      x1     x2   x3     x4
0    1.0    2.0    3    4.0
1    1.0    6.0    7    4.0
2   11.0    6.0   12   13.0
3  100.0  200.0  300  400.0
4   20.0   40.0   60  400.0 

      x1     x2   x3     x4
0    1.0    2.0    3    4.0
1   11.0    6.0    7   13.0
2   11.0  200.0   12   13.0
3  100.0  200.0  300  400.0
4   20.0   40.0   60    NaN 

      x1     x2   x3     x4
0    1.0    2.0    3    4.0
1   33.0    6.0    7  400.0
2   11.0   23.0   12   13.0
3  100.0  200.0  300  400.0
4   20.0   40.0   60  400.0

2.13 數據映射

映射函數apply的目的就是將用戶指定的函數運用到數據集的縱軸(即各個變量)或橫軸(即各個行)。實例:

# 輸入:
# 查看各列和各行是否有缺失
# 創建一個判斷對象是否含缺失的匿名函數
import pandas as pd
import numpy as np
df = pd.DataFrame([[1,2,3,4],[np.NaN,6,7,np.NaN],[11,np.NaN,12,13],
                 [100,200,300,400],[20,40,60,np.NaN]], columns = ['x1','x2','x3','x4'])
isnull = lambda x : any(pd.isnull(x))
print(df.apply(func = isnull, axis = 0),'\n') # axis=0表示將isnull函數映射到各列
print(df.apply(func = isnull, axis = 1)) # axis=1表示將isnull函數映射到各行
# 輸出:
x1     True
x2     True
x3    False
x4     True
dtype: bool 

0    False
1     True
2     True
3    False
4     True
dtype: bool

需要計算每個學生的總成績,或各科的平均分,也可以用apply函數實現。實例:

# 輸入:
import pandas as pd
import numpy as np
df = pd.DataFrame([['a',99,88,77],['b',98,87,76],['c',100,90,80],
                 ['d',95,80,85],['e',90,89,99]], columns = ['name','chinese','math','english'])
print(df)
df['total'] = df.iloc[:,1:5].apply(func = np.sum, axis = 1) # 每個學生的總成績
print(df)
avg = df.iloc[:,1:5].apply(func = np.mean, axis = 0) # 每門學科的平均成績
print(avg)
# 輸出:
  name  chinese  math  english
0    a       99    88       77
1    b       98    87       76
2    c      100    90       80
3    d       95    80       85
4    e       90    89       99
  name  chinese  math  english  total
0    a       99    88       77    264
1    b       98    87       76    261
2    c      100    90       80    270
3    d       95    80       85    260
4    e       90    89       99    278
chinese     96.4
math        86.8
english     83.4
total      266.6
dtype: float64

2.14 數據彙總

如果你想要做類似SQL中的聚合操作,pandas也提供了實現該功能的函數,即groupby函數與aggregate函數的搭配使用。

# 輸入
import pandas as pd
import numpy as np
df = pd.DataFrame([['a','f',99,88,77],['b','m',98,87,76],['c','m',100,90,80],
                 ['d','f',95,80,85],['e','m',90,89,99]], columns = ['name','sex','chinese','math','english'])
# 對性別gender做分組統計各數值型變量的平均值
groupby_gender = df.groupby(['sex'])
b = groupby_gender.aggregate(np.mean)
print(b)
# 對性別gender和班級class兩個變量做分組統計各數值型變量的平均值
grouped = df.groupby(['sex','name'])
c = grouped.aggregate(np.mean)
print(c)
# 對chinese算平均值,對math算中位數
d = grouped.aggregate({'chinese':np.mean,'math':np.median}) 
print(d)
# 輸出
     chinese       math  english
sex                             
f       97.0  84.000000     81.0
m       96.0  88.666667     85.0
          chinese  math  english
sex name                        
f   a          99    88       77
    d          95    80       85
m   b          98    87       76
    c         100    90       80
    e          90    89       99
          chinese  math
sex name               
f   a          99    88
    d          95    80
m   b          98    87
    c         100    90
    e          90    89

2.15 數據集的縱向合併

如果你手中有多張數據結構一致的excel表格,你需要將這些表格合併到一起,你會怎麼做?複製粘貼?是不是太慢了,這裏教你使用Python完成數據的批量合併。
實例:

import os
import pandas as pd
# 指定數據文件所在的路徑
path = 'D:\\data file\\data1\\'
# 羅列路徑下的文件名稱
filenames = os.listdir(path)
# 通過for循環完成數據的堆疊
dataframes = []
for file in filenames:
    dataframes.append(pd.read_excle(path  + file))
alldata = pd.concat(dataframes, ignore_index=True)
alldata.head()

注意:pd.concat函數的第一個參數一定要是一個可迭代對象。故在代碼中對dataframe初始化爲列表結構。

2.16 數據集的橫向擴展

如果你所需的數據集來自於多張表,而這些表之間存在一些公共的字段用於觀測行的匹配,換句話說,你需要在excel使用vlookup這樣的函數完成數據的連接。藉助於pandas中merge函數完成兩個數據集的連接。如果你的兩張表有公共字段,而且字段名稱完全一致,merge函數會自動查詢這些字段,並以這些字段作爲連接的依據。如果兩張表中含公共字段,但名稱不一致,如Id與id,這個時候就需要left_on和right_on兩個參數的使用了。
語法:

pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None,
        left_index=False, right_index=False,sort=False,
        suffixes=('_x','_y'), copy=True, indicator=False)
  • left,right:爲需要連接的兩張表;
  • how:默認對兩張表進行內連,‘right’,‘left’爲右連和左連;
  • on:指定關聯兩張表的公共字段;
  • left_on,right_on:指定left表和right表中需要關聯的字段;
  • left_index,right_index:指定left表和right表中需要關聯的行索引
    實例:
# 有公共字段且字段名稱一樣的兩個數據集的連接
merge_data = pd.merge(user_info, economy_info, how = 'left') 
merge_data.head()
# 有公共字段且字段名稱不一樣的兩個數據集的連接
merge_data2 = pd.merge(user_info, economy_info, how = 'left', left_on = 'ID', right_on = 'id')
merge_data2.head()

2.17 離散變量的啞變量處理

在建模過程中,往往會有一些離散變量,如學歷、收入等級,用戶會員等級。這些變量直接放入到模型中(如迴歸模型)是有問題的(即使你已經用1,2,3…等數據表示),爲解決這個問題,我們通常是將這些變量進行啞變量處理。如果離散變量有N種水平,就需要構造N-1個變量,每一個變量均用0和1的值來表示。這時需要用到pandas模塊中的get_dummies函數。
實例:

# 輸入:
import pandas as pd
import numpy as np
a = pd.DataFrame([['a','f',99,88,77],['b','m',98,87,76],['c','m',100,90,80],
                 ['d','f',95,80,85],['e','m',90,89,99]], columns = ['name','sex','chinese','math','english'])
print(a)
b = pd.get_dummies(a, columns = ['sex']).head() # 啞變量處理
print(b)
c = b.drop(['sex_f'], axis = 1).head() # 刪除字段sex_f
print(c)
# 輸出:
  name sex  chinese  math  english
0    a   f       99    88       77
1    b   m       98    87       76
2    c   m      100    90       80
3    d   f       95    80       85
4    e   m       90    89       99
  name  chinese  math  english  sex_f  sex_m
0    a       99    88       77      1      0
1    b       98    87       76      0      1
2    c      100    90       80      0      1
3    d       95    80       85      1      0
4    e       90    89       99      0      1
  name  chinese  math  english  sex_m
0    a       99    88       77      0
1    b       98    87       76      1
2    c      100    90       80      1
3    d       95    80       85      0
4    e       90    89       99      1

千萬記得,如果你的變量進行了啞變量處理,建模時要記得刪除原離散變量中的某一個水平,如性別中刪除sex_f。刪除的變量,就表示性別中,以女性(f)爲參照組。

2.18 連續變量的分段

把連續變量進行分段處理,如年齡需要分成未成年、青年、中年和老年;收入需要分成低收入羣體、中等收入羣體和高收入羣體,這時可以用到pandas.cut()函數。
語法:

pandas.cut(x, bins, right=True, labels=None, retbins=False, precision=3,include_lowest=False)
  • x:表示需要切割處理的變量;
  • bins:表示切割後的邊界值,即分組情況;
  • right:等於False時表示分段的數據區間不包含上限;
  • labels:對應bins切割區間的標籤
    實例:
# 輸入:
import numpy as np
import pandas as pd
np.random.seed(1)
age = np.random.randint(low = 12, high = 80, size =1000) # 隨機生成一個年齡的字段
age = pd.Series(age) # 化爲序列
print(age.head(),'\n')
age_cut = pd.cut(age, bins = [0,18,45,60,80], right = False, labels = ['未成年','青年','中年','老年'])
print(age_cut.head()) # 把年齡序列切割爲四個區間,18歲以下爲未成年;18~45歲爲青年;45~60歲爲中年;60歲以上爲老年
# 輸出:
0    49
1    24
2    21
3    17
4    76
dtype: int32 

0     中年
1     青年
2     青年
3    未成年
4     老年
dtype: category
Categories (4, object): [未成年 < 青年 < 中年 < 老年]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章