上文交代了一些囉嗦事,本文開始,就要來點實際的了。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
結果以下所示:
因爲算法邏輯不是很複雜,抽象起來也就三個狀況,因此經過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
最終結果以下:
本文要點:
Pandas讀取CSV文件方法;
Pandas的追加新列方法:df.ix[condition, 'newcolname'] = value(標量或者向量) 或者 df['newcolname'] = value(標量或者向量);
Pandas的df.apply()對列進行迭代的方法;
Pandas的df中的一些經常使用的數據處理方法;
Pandas的Series的簡單邏輯操做& | ~;
看,是否是很簡單。
未完待續……