個人Pandas應用場景(2)

上文交代了一些囉嗦事,本文開始,就要來點實際的了。html

先來一個比較簡單的場景:python

Given:一個包括N(極其複雜,這裏取3個)個列的DataFrame:df,df包括index;算法

And:對df全部列元素進行一些處理,獲得df的一個變換後的df_new;app

And:對df_new的某些列作極其複雜的判斷,獲得新的列result;機器學習

When:須要將要根據result對df進行分析;函數

Then:將result追加到df中。學習

上述的場景是個人一個算法驗證的場景,簡單地說,就是須要經過對原始數據進行變換,而後獲得新的列,而後追加到原始數據中,最後進行分析。spa

首先構造一下模擬的數據吧。咱們的數據經過隨機數產生,爲10*3的數據,每一列的名稱爲A/B/C,放到csv格式的文件中,文件內容以下所示:code

A,B,C
4.556325895482557,4.9467487190814206,9.240498646959768
6.798122785026925,9.205498509979439,6.495701755638054
1.7088666262153485,1.9490481646738644,5.016719349132167
7.68793618140002,4.288529993589748,0.4479283787649413
0.22238136867848257,2.861119654701667,5.296500633944277
3.8352546975711,0.29287579880826087,1.0438719791356377
4.603712955967749,5.647815101448938,0.6054047619225811
6.916870514198006,8.903690009637602,4.836793019361064
9.845396552800361,0.8159084013183737,0.8425827491512894
2.425545747141858,7.353661205806686,2.982326067390466

通常字符型的文件會以上述的逗號隔開的方式存儲,經過pandas的read_csv()能夠方便的讀入數據到DataFrame,以下代碼所示:htm

import pandas as pd
import numpy as np

df = pd.read_csv('d:/data.csv')

pd.read_csv()默認的讀法就是上述代碼那樣,他會將第一行當作列名讀入。假如咱們的csv數據中不包含列名,能夠經過header=None來禁止將第一行當作列名;假如csv數據中沒有列名,而咱們想要指定列名,這也是我常常作的,能夠經過name=[]參數,經過一個列表指定全部列的名稱。指定列名有一個好處就是列名能夠當作DataFrame的屬性,對列進行訪問,後續會介紹。

讀進來的輸入以下所示:

 

而後,咱們須要對df進行變換。

這裏模擬一種變換,就是將每一列進行均值位0,方差爲1的變換,代碼以下:

import pandas as pd
import numpy as np

df = pd.read_csv('d:/data.csv')

df_new = df.apply(lambda col: (col - col.mean()) * 1.0 / col.std())
df_new

其中,df.apply()函數是df的一個函數式接口,表示依次對df的列(A/B/C)進行迭代,其參數爲一個lambda表達式,lambda的參數col就表示df的一個列。

col實際上是Series的一個對象,其中包含大量的數據處理方法,這裏實用的是其中兩個:均值mean()和std()方差。

lambda的實現部分使用了Pandas的向量化的運算方式,也就是說col雖然是一個Series,可是咱們對其操做就像操做一個標量同樣,可是自動傳播給全部的元素。

通過上述代碼的運算,每一列都被映射到新的df_new中,這個方式在機器學習、數據挖掘中很常見。結果以下圖所示。

  A B C
0 -0.102247 0.100417 1.865099
1 0.652462 1.435738 0.944303
2 -1.060854 -0.839506 0.448149
3 0.952021 -0.105966 -1.084541
4 -1.561285 -0.553528 0.542008
5 -0.344998 -1.358795 -0.884620
6 -0.086294 0.320234 -1.031713
7 0.692439 1.341107 0.387790
8 1.678338 -1.194799 -0.952147
9 -0.819582 0.855099 -0.234328

如今,咱們要使用df_new的數據計算咱們的結果了。若是邏輯很簡單,則能夠直接經過Pandas的IF THEN邏輯實現,複雜的算法能夠須要本身一行一行的遍歷df_new,經過if else邏輯實現。咱們先說一個簡單的狀況。

假如,咱們的算法是這樣的:若是A>0.5而且B<0.5,則爲True,不然若是C>0.5,則爲True,則否爲False,實現代碼以下所示:

import pandas as pd
import numpy as np

df = pd.read_csv('d:/data.csv')

df_new = df.apply(lambda col: (col - col.mean()) * 1.0 / col.std())

df_new.ix[(df_new.A > 0.5) & (df_new.B < 0.5), 'Result'] = True
df_new.ix[~((df_new.A > 0.5) & (df_new.B < 0.5)) & (df_new.C > 0.5), 'Result'] = True
df_new.ix[~(~((df_new.A > 0.5) & (df_new.B < 0.5)) & (df_new.C > 0.5)), 'Result'] = False
df_new

結果以下所示:

 

Out[68]:
  A B C Result
0 -0.102247 0.100417 1.865099 True
1 0.652462 1.435738 0.944303 True
2 -1.060854 -0.839506 0.448149 False
3 0.952021 -0.105966 -1.084541 False
4 -1.561285 -0.553528 0.542008 True
5 -0.344998 -1.358795 -0.884620 False
6 -0.086294 0.320234 -1.031713 False
7 0.692439 1.341107 0.387790 False
8 1.678338 -1.194799 -0.952147 False
9 -0.819582 0.855099 -0.234328 False

因爲算法邏輯不是很複雜,抽象起來也就三個狀況,因此經過Pandas的IF Then的機制實現了Result列的添加。

DataFrame.ix[condition, 'newOrExistsColname'] = value,具體能夠參考Pandas的十分鐘入門教程,開始就是講這個的。

須要強調的是咱們經過df_new.A這樣的方式訪問A列元素,這是Pandas的方便之處;而且各類比較和& ~操做都是針對元素的;而且只有index相同的元素纔會比較,並且Result也是添加到對應的index列的。

假如算法實如今太複雜,不是簡單的集中狀況能夠講清楚的,這個時候我採用的方法就是C++和Java中最常使用的for循環了,幾乎萬能。還以上述的算法爲例,代碼以下:

import pandas as pd
import numpy as np

df = pd.read_csv('d:/data.csv')

df_new = df.apply(lambda col: (col - col.mean()) * 1.0 / col.std())

result = pd.Series([False]*len(df_new))
for i in range(len(df_new)):
    item = df_new.iloc[i, :]
    if item.A > 0.5 and item.B < 0.5:
        result[i] = True
    elif item.C > 0.5:
        result[i] = True
    else:
        result[i] = False # unnecessary
df_new['Result'] = result
df_new

 

代碼中一片濃郁的C、Java風格,雖然不那麼函數式也不向量化,可是我就是感受熟悉,畢竟我最先學習的是C。

首先,我定義了一個Series,初始化爲False,而後經過一個for循環,遍歷df_new的全部行,依次爲result賦值,最後,經過df_new['newcolname']=的方式將resut追加到df_new中了。

注意,當將Series往DataFrame或者Series中拼接的時候,默認的都是安裝index對齊的,也就是行的index一致的纔會拼接到一塊兒,而與行的順序無關,這點是Pandas的強大之處(數據的自動對齊,在groupby以後的數據中特別有用),千萬別忽視了這點。

最後,咱們要將df_new.Result追加給df,由於df_new.Result本質上仍是一個Series,因此上述的代碼中已經有了一種方式:df.ix['Result']=df_new.Result。

代碼以下:

import pandas as pd
import numpy as np

df = pd.read_csv('d:/data.csv')

df_new = df.apply(lambda col: (col - col.mean()) * 1.0 / col.std())

result = pd.Series([False]*len(df_new))
for i in range(len(df_new)):
    item = df_new.iloc[i, :]
    if item.A > 0.5 and item.B < 0.5:
        result[i] = True
    elif item.C > 0.5:
        result[i] = True
    else:
        result[i] = False # unnecessary
df_new['Result'] = result
df['Result'] = df_new.Result
df

 

最終結果以下:

 

Out[77]:
  A B C Result
0 4.556326 4.946749 9.240499 True
1 6.798123 9.205499 6.495702 True
2 1.708867 1.949048 5.016719 False
3 7.687936 4.288530 0.447928 True
4 0.222381 2.861120 5.296501 True
5 3.835255 0.292876 1.043872 False
6 4.603713 5.647815 0.605405 False
7 6.916871 8.903690 4.836793 False
8 9.845397 0.815908 0.842583 True
9 2.425546 7.353661 2.982326 False

 

 

本文要點:

Pandas讀取CSV文件方法;

Pandas的追加新列方法:df.ix[condition, 'newcolname'] = value(標量或者向量) 或者 df['newcolname'] = value(標量或者向量);

Pandas的df.apply()對列進行迭代的方法;

Pandas的df中的一些經常使用的數據處理方法;

Pandas的Series的簡單邏輯操做& | ~;

看,是否是很簡單。

未完待續……

相關文章
相關標籤/搜索