1. 程式人生 > >pandas資料處理

pandas資料處理

用pandas進行資料分析,對資料預處理,以及簡單例子說明

  • concat

用於將2個DataFrame連線到一起,一般是將訓練集與測試集連線在一起對屬性值進行預處理。個人感覺這樣處理是可以的,因為對屬性值的處理一般要求數值越多越好,而且對訓練集與測試集的資料預處理要求要是一樣的。只要在訓練模型的時候講2者分開就行。

相同列合併到一起,不同時新建列,預設值為NaN

df1 =DataFrame({'a':[1,2,3],'b':[4,5,6]})

df2 =DataFrame({'a':['a','b','c'],'c':['e','f','g']})

df = pd.concat([df1,df2])

print df

"""

   a   b    c

0  1   4  NaN

1  2   5  NaN

2  3   6  NaN

0  a NaN    e

1  b NaN    f

2  c NaN    g

"""

df.reset_index(inplace=True)

print df

"""

   index  a  b    c

0      0  1  4  NaN

1      1  2  5  NaN

2      2  3  6  NaN

3      0  a NaN   e

4      1  b NaN   f

5      2  c NaN   g

"""

df.drop('index', axis=1,inplace=True)

print df

"""

   a   b    c

0  1   4  NaN

1  2   5  NaN

2  3   6  NaN

3  a NaN    e

4  b NaN    f

5  c NaN    g

"""

df =df.reindex_axis(df1.columns, axis=1)

print df

"""

   a   b

0  1   4

1  2   5

2  3   6

3  a NaN

4  b NaN

5  c NaN

"""

df.shape[0],df.shape[1]分別獲取行數、列數

print df.shape[1],"columns:", df.columns.values

print "Row count:",df.shape[0]

"""

2 columns: ['a' 'b']

Row count: 6

"""

  • map()

Series 或 DataFrame 的列都可以呼叫一個map()方法。該方法接受一個函式或字典作為引數,並將之應用於該列的每一個元素,將元素值對映為另一個值。多用於資料離散化。

df = DataFrame(np.arange(8).reshape(4,2),columns= ['a','b'])

df['c'] = df['a'].map(lambda x: x+1)

print df

"""

   a  b  c

0  0  1  1

1  2  3  3

2  4  5  5

3  6  7  7

"""

也可以在原來列修改值。df['a'] =df['a']. map({xxx})

"""

   a  b

0  1  1

1  3  3

2  5  5

3  7  7

"""

lambda函式也可以用自定義函式實現

當元素值少時,可以直接用字典修改:

df1 =DataFrame({'a':['female','male'],'b':['male','female']})

df1['a'] =df1['a'].map({'female':0, 'male':1})

print df1

"""

   a       b

0  0    male

1  1  female

"""

  •  isin()

判斷某一列元素是否屬於列表裡的元素,返回True False列表,如果為True,則對該行元素進行操作,False時不操作

df = DataFrame({'columns1':['a','b','c'],'columns2':['c','d','e']})

df.columns1[df.columns1.isin(['a','b'])]= 'cc'

print df

"""

  columns1columns2

0      cc        c

1      cc        d

2       c        e

"""

  •  採用均值/出現次數設定missing值
對於一列數字,要獲取平均值,如下:

df =DataFrame(np.arange(8).reshape(4,2),columns=['a','b'])

median =df.a.dropna().median()

print 'median:',median

"""

pingjunzhi:

median: 3.0

"""

對於一列非數字,例如字元,要找到出現頻率最高的字元賦值給missing值

df2 = DataFrame({'a':['a','b','a'],'c':['e','f','g']})

freq_max =df2.c.dropna().mode().values

print 'freq_max:',freq_max

"""

freq_max: ['a']

"""

試了下,如果求列c,各頻率相同,則返回空列表

  •  屬性數字化----列舉

某一屬性,其值表示為字元,且範圍較少時,可選擇使用列舉進行數字化

用np.unique()生成唯一化後的元素,在用enumerate()生成對應元組,轉化為列表後生成字典。再對字典進行map操作,即可實現數值化。

df2 =DataFrame({'aa':['a','b','c'],'dd':['d','e','f']})

unique_value =list(enumerate(np.unique(df2.aa)))

print'unique_value:',unique_value

"""

unique_value: [(0, 'a'), (1, 'b'), (2, 'c')]

"""

dict = {key:value forvalue,key in unique_value}

for i in dict.keys():

    print i,':',dict[i]

"""

a : 0

c : 2

b : 1

"""

df2.aa = df2.aa.map(lambdax:dict[x]).astype(int)

print df2

"""

   aa dd

0   0  d

1   1  e

2   2  f

"""

  • 啞變數

作用條件與列舉類似,屬性值範圍不大時,會為每一個值生成新的一列。結果需要concat

df =DataFrame({'column1':['aa','bb','cc'], 'column2':['dd','ee','ff']})

dummy_df_column1 =pd.get_dummies(df.column1)

print'dummy_df_column1:\n',dummy_df_column1

"""

dummy_df_column1:

   aa  bb  cc

0   1   0   0

1   0   1   0

2   0   0   1

"""

dummy_df_column1 =dummy_df_column1.rename(columns=lambda x : 'dummy_'+str(x))

print 'dummy_df_column1:\n',dummy_df_column1

"""

dummy_df_column1:

  dummy_aa  dummy_bb  dummy_cc

0        1         0         0

1        0         1         0

2        0         0         1

"""

df =pd.concat([df,dummy_df_column1],axis=1)

print df

"""

  column1column2  dummy_aa  dummy_bb dummy_cc

0     aa      dd         1         0         0

1     bb      ee         0         1         0

2     cc      ff            0         0         1

"""

每個屬性值對應一列,所以屬性值很多的情況下不適用,會生成較大的df。將啞變數變換後的新的屬性列直接concat到原來的df中即可。

  •  loc()

loc()對應列選取多行,第一個元素取行,第二個元素對應列,預設情況下為所有列

df =DataFrame({'a':[1,2,3,4],'b':[5,6,7,8]})

print df.loc[(df.a.values> 2)] #取出a列中值大於2的所有列的值,原df的值不變

"""

   a  b

2  3  7

3  4  8

"""

print df.loc[(df.a.values> 2),'a'] #只作用於a列,輸出a列

"""

2    3

3    4

Name: a, dtype: int64

"""

df.loc[(df.a.values >2),'a'] = 2 #對其賦值,則改變df的值

print 'df = \n',df

"""

df =

   a  b

0  1  5

1  2  6

2  2  7

3  2  8

"""

  •  bining面元組合

主要用於產生一個有序分類

df =DataFrame(np.arange(16).reshape(8,2),columns=['aa','bb'])

print df

"""

   aa  bb

0   0   1

1   2   3

2   4   5

3   6   7

4   8   9

5  10  11

6  12  13

7  14  15

"""

先用pd.qcut()將資料分為若干份,對應新的一列,元素為一個範圍字串,仍然需要量化

df['cc'] = pd.qcut(df.aa,2) #cc加入到原df中,不需要concat

print df.cc

"""

0     [0, 7]

1     [0, 7]

2     [0, 7]

3     [0, 7]

4    (7, 14]

5    (7, 14]

6    (7, 14]

7    (7, 14]

Name: aa, dtype: category

Categories (2, object): [[0, 7] < (7, 14]]

"""

print pd.qcut(df.bb,4)

"""

0      [1,4.5]

1      [1,4.5]

2      (4.5,8]

3      (4.5,8]

4     (8,11.5]

5     (8,11.5]

6    (11.5,15]

7    (11.5,15]

Name: bb, dtype: category

Categories (4, object): [[1, 4.5] < (4.5, 8]< (8, 11.5] < (11.5, 15]]

"""

此處是均等分為2份或4份,實際資料中當數值並非均勻分佈時,生成的bining應該不是均勻分佈

還有就是貌似qcut幾份有最大值限制,我實驗的時候貌似最大隻能分到9,配置為10則出錯。想到分太多維太佔用記憶體,這點也可以理解了。

 df['dd'] = pd.qcut(df.bb,2) 

print df

"""

   aa  bb      cc       dd

0   0   1  [0, 7]   [1, 8]

1   2   3  [0, 7]   [1, 8]

2   4   5  [0, 7]   [1, 8]

3   6   7  [0, 7]   [1, 8]

4   8   9  (7,14]  (8, 15]

5  10  11  (7,14]  (8, 15]

6  12  13  (7,14]  (8, 15]

7  14  15  (7,14]  (8, 15]

"""

有個奇怪的現象,此處如果df['cc'],df['dd']則列'cc','dd'加入到df中,如果df.cc,df.dd則沒有加入df,需要concat

如果DataFrame對列的引用兩種方式相同,為什麼要有這種區別?

分類後元素只是string,還要進行數字化,可以採用enumerate,dummy,factorize。

dummy_df =pd.get_dummies(df.cc).rename(columns=lambda x:'dummy_' + str(x) )

df =pd.concat([df,dummy_df],axis=1).drop(['cc','dd'],axis=1)

print df

"""

   aa  bb dummy_[0, 7]  dummy_(7, 14]

0   0   1            1              0

1   2   3            1              0

2   4   5            1              0

3   6   7            1              0

4   8   9            0              1

5  10  11            0              1

6  12  13            0              1

7  14  15            0              1

"""

"""

這部分沒玩起來,不知道怎麼回事啊  ???

cc_enumerate = list(enumerate(np.unique(df.cc)))

cc_dict = {key:value for value,key in cc_enumerate}

for key in cc_dict.keys():

    printkey,':',cc_dict[key]

    printtype(key)

df['cc'] = df.cc.map(lambdax:cc_dict[x]).astype(int)

#print df.cc

"""

  •  factorize()
實驗了一把,主要是將列表中字母值用列舉表示,相同值用同一數字。結果只生成一列,可以在原來列中操作,後面的引數[0]不可去掉或改為其他值,原因暫時我也不知道

df =DataFrame({'column1':['a','b','a'],'column2':['e','f','g']})

df.column1 =pd.factorize(df.column1)[0]

df.column2 =pd.factorize(df.column2)[0]

print df

"""

  column1  column2

0       0        0

1       1        1

2       0        2

"""

實驗的時候對同一屬性做dummy以及factorize數字化時,貌似dummy效果會好一點。???

  • scaler

規範化,把資料壓縮到一個範圍,具體應用場景,不清楚

df =DataFrame({'aa':[5,10,15,20],'bb':[0,3,6,9],'cc':[1000,0,500,50],'dd':[1,100,3,2]})

scaler =preprocessing.StandardScaler()

df.aa = scaler.fit_transform(df.aa)

df.bb =scaler.fit_transform(df.bb)

df.cc =scaler.fit_transform(df.cc)

df.dd =scaler.fit_transform(df.dd)

print df

"""

        aa        bb        cc        dd

0 -1.341641 -1.341641  1.517239 -0.600832

1 -0.447214 -0.447214 -0.959886  1.731810

2 0.447214  0.447214  0.278677 -0.553708

3 1.341641  1.341641 -0.836030-0.577270

"""

 還有很多對資料預處理的操作,missing值的操作,屬性值的特性分析,特徵提取等等。

當對資料進行離散化時,一個小結就是:

  1. 屬性集可以分為2種類型:Quantitative(定量) and Qualitative(定性)。                                                                                                                                                                           定量是指可以按照某種規則進行排序,一般指數字類,例如年齡、工資等。                                                                                                                                                                定性不容易排序,一般指字串或數字與字串的組合,如姓名等。
  2. 定量資料轉換:scale以及bining
  • scaling:資料縮放,當屬性值範圍較大時,可以將其按照比例進行縮小,範圍可以從0-1,-1-1,具體如何設定範圍,不清楚。基於神經網路演算法,或者對基於距離的分類或聚類有效。對基於相似度而不是距離的演算法,如隨機森林,效果不一定好
  • bining:面元組合,產生一個有序的分類值,例如年齡,工資等。呼叫pandas.qcut(),利用分位數對整個數值範圍劃分為幾個bin,實驗過程中,貌似有個最大bin數,9,當配置大於9時即出錯。所以應該還是適用於範圍並非太大的屬性集。分類後產生的bin列,元素為string範圍值,可通過啞變數、列舉或factorize進行數值化。

         3.定性資料轉換:列舉、啞變數、因子分解

  • 列舉enumerate與因式分解factorize感覺差不多,都是將該列相同元素對映為一個數值。數值範圍為連續自然數
  • 啞變數dummy,單獨為不同元素生成一列值,用0,1表示,主要用於標稱屬性或二元屬性
  • 當屬性值範圍較多時,啞變數會佔用太大記憶體。另外使用隨機森林生成feature_importance時,啞變數的列向量會分化了該屬性的重要性,效果不如factorize好啊。