iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 14
0
AI & Machine Learning

玩轉資料與機器學習-以自然語言處理為例系列 第 14

Pandas(Python中的Excel)Day4-DataFrame的新增、迴圈與刪除

提醒: 本篇文章的code在這裡: Titanic

新增資料

新增資料有兩種可能的意思: 要新增column或是要新增row,在pandas可透過concat完成這件事。順帶一提,concat是concatenate的縮寫,其實是把兩張DataFrame併在一起的意思,不過這邊純粹是整併同樣順序或是同樣欄位的DataFrame,如果你希望透過某個欄位的值對應出其他欄位,那麼你需要尋找的語法叫做join,由於這屬於相對進階的操作,並不會在這一系列的文章中提及。

1. 新增rows

這邊用一個案例,假設你發現要拿來預測的資料的類別比例與訓練資料的比例不符,(你可以透過上傳全部為1的檔案去看分數判斷每個類別的比例(噓...我什麼都沒說)),在鐵達尼號來說可能你發現生還者的比例在測試資料比較高。那麼你可能要複製一些生還者的資料,已使預測結果的比例比較接近測試資料,增加比賽準確度。

num_NonSurvived = df.groupby('Survived').count()['PassengerId'][0]  # 死亡者的個數
num_Survived = df.groupby('Survived').count()['PassengerId'][1]  # 生還者的個數
duplicate_length = num_NonSurvived - num_Survived
print(num_NonSurvived)
print(num_Survived)
print(duplicate_length)
duplicate_indices = np.random.choice(df[df['Survived'] == 1].index, duplicate_length)  #choice可以直接幫你從一個list中,隨機挑選出指定size的item。這便則可以挑選出,特定size的index值。
df_duplicate = df.loc[duplicate_indices].copy()  # 索引出隨機挑選的index的row
print(len(df))
df = pd.concat([df, df_duplicate], ignore_index=True)  # 把挑選出來要負的的row,新增上原本的DataFrame
print(len(df))
df

https://ithelp.ithome.com.tw/upload/images/20171215/201075761Z2iiM1yse.jpg

2. 新增columns(DataFrame的迴圈)

這裡當然也可以用concat去做(設定axis=1),不過一般你要做出一個與DataFrame等長的、而且直接對應到rowID的資料欄位,除了跑回圈取得之外,也很難用其他方法做出來,所以這邊就來介紹一下,DataFrame跑回圈的幾種方法。

  • 透過applyfunction: 這種方式的效能比下面的方式好。假設這邊我們希望可以增加一個資料欄位是Name的長度。
df['Name_Length'] = 0 # 先透過這種方式新增好欄位做準備,下面執行效能會好很多
def cal_namelength(row):
    if pd.notnull(row['Name']):
        row['Name_Length'] = len(row['Name'])
    else:
        row['Name_Length'] = 0
    return row
df = df.apply(cal_namelength, axis=1)  # 記得: 1.要把新的df指派給原本的df才會成功更新。 2. axis要設定為1,才會以row為單位跑回圈。
# 順帶一提,其實Series也可以直接使用applyfunction,詳情見本篇文章最後一部分。

https://ithelp.ithome.com.tw/upload/images/20171215/20107576PjneiA2H4c.jpg

  • iterrows: 請大家非不得已不要使用這種方式,若是透過這種方法更新或是新增資料在原本的DataFrame中,效能上會是很大的負擔。如果你的資料量沒有很大,更動的資料也沒有很多,那麼你也可以考慮這個方式,操作上會稍微彈性一點。這邊示範把Age這個連續變數,變成類別變數,這個動作在英文叫做discretization,後面會細緻的說明如何做。這邊大家先掠過怎麼選擇切分的range,看得懂新增欄位的功能即可。
df['Age_cat'] = 0
for idx, row in df.iterrows():  # 請務必記得加上idx,不然跑回圈的item會變成(idx, row)
    Age = row['Age']
    if Age < 20.315:
        Age_cat = 0
    elif Age < 40.21:
        Age_cat = 1
    elif Age < 60.1049:
        Age_cat = 2
    else:
        Age_cat = 3
    df.loc[idx, 'Age_cat'] = Age_cat
df

https://ithelp.ithome.com.tw/upload/images/20171215/20107576z1kCNxtpDU.jpg

刪除資料

刪除資料一樣可以分為丟掉column或是row。

df.drop(['Age_cat', 'Name_Length'], axis=1, inplace=True) #把['Age_cat', 'Name_Length']丟掉,記得axis=1代表丟的是columns。inplace則是代表把更新後的df指派給原本的df。
df

https://ithelp.ithome.com.tw/upload/images/20171215/201075765Olsdxarjm.jpg

df_line0 = df.loc[:2].copy()
print(len(df))
df.drop(range(3), inplace=True)
print(len(df))
df = pd.concat([df, df_line0], ignore_index=True)
print(len(df))

https://ithelp.ithome.com.tw/upload/images/20171215/20107576pUIpJvGqNe.jpg

groupby

df.groupby('Age_cat').count()  #每一個類別的次數
df.groupby('Age_cat').mean()  #每一個類別個項目的平均
df.groupby('Age_cat').median()  #每一個類別個別項目的中位數
df.groupby('Age_cat').std()  #每一個類別個別項目的標準差

https://ithelp.ithome.com.tw/upload/images/20171215/20107576fpPb44hQOd.jpg

sort_values

df.sort_values('Age', ascending=False)

https://ithelp.ithome.com.tw/upload/images/20171215/20107576Ig9hElcAyX.jpg

小小的遊戲

pandas的教程就到這邊告一段落拉。我知道,學這些基本工具很痛苦,不過這大約也是我覺得最重要的基礎技能。所以為了讓大家有繼續看下去的動力,這邊來給大家一個好玩的小專案,大家可以自己玩玩。不過因為使用到一些自然語言處理的技術,後面的文章會詳細的談,大家先玩玩就好。總之,我們可以來看一下,哪一些詞彙在人名當中出現比較多次。

  1. 把人名統整起來,並做好前處理(斷詞、去除表點符號與停用字)
from string import punctuation
from collections import Counter
df_name = df[['Name']]
def processname(name):
    if type(name) == str:
        for pun in punctuation:
            name = name.replace(pun, " ")
        terms = [term for term in name.split() if term != " "]
        return terms
    else:
        return []
df_name['processed'] = df['Name'].apply(processname)
df_name

https://ithelp.ithome.com.tw/upload/images/20171215/20107576z6737R0zYj.jpg

  1. 排序每一個字出現多寡
all_terms = []
for terms in df_name['processed']:
    all_terms.extend(terms)
sorted(dict(Counter(all_terms)).items(), key=lambda x:x[1], reverse=True)

https://ithelp.ithome.com.tw/upload/images/20171215/20107576eXJMNud2e1.jpg

3.畫出漂亮的文字雲

import matplotlib.pyplot as plt
from wordcloud import WordCloud

wordcloud = WordCloud()
wordcloud.generate_from_frequencies(frequencies=dict(Counter(all_terms)))
plt.figure()
plt.imshow(wordcloud, interpolation="bilinear")
plt.axis("off")
plt.show()

https://ithelp.ithome.com.tw/upload/images/20171215/20107576GSN6K8FXgw.png


上一篇
Pandas(Python中的Excel)Day3-DataFrame的索引與更新
下一篇
英文自然語言處理基礎
系列文
玩轉資料與機器學習-以自然語言處理為例31

尚未有邦友留言

立即登入留言