四、數據處理
(1)缺失值
查看缺失情況:
1 data.isnull()#查看所有缺失值 2 data.isnull().any()#獲取含有缺失值的列 3 data.isnull().all()#獲取全部為NA的列
刪除缺失值:
data2=data.dropna()
利用sklearn替換缺失值。當缺失值為數值型數據時,可用利用均值來替換
data.index=data['name']#將第一列作為索引data=data.drop(['name'],axis=1)#刪除第一列 nan_model=Imputer(missing_values='NaN',strategy='mean',axis=0)#按照行均值替換對應缺失值。 nan_result=nan_model.fit_transform(data)
利用pandas替換缺失值(常用)
data.fillna(0) #缺失值用0替換 data.fillna(method='pad')#用前面的值替換 data.fillna(method='backfill')#用后面的值替換
一個實例(https://blog.csdn.net/weixin_41576911/article/details/83744417):
import pandas as pd
import numpy as np from sklearn.preprocessing import Imputer df = pd.DataFrame(np.random.randn(6,4),columns = list('abcd')) df.iloc[4,3] = np.nan#iloc是選擇行和列 df.loc[3] = np.nan#loc是選擇行 print(df) print(df.loc[0:2,3]) nan_all=df.isnull() print(nan_all) drop = df.dropna()#丟棄包含缺失值的行記錄 print(drop)
又一個實例(https://www.jianshu.com/p/d750ba9075dd,寫得比我清楚,強推!):
# 刪除完全缺失的行,若不指定參數how,則刪除的是所有含有nan的行
>>> data.shape
(6578, 7) >>> data_drop_nan = data.dropna(how='all') >>> data_drop_nan.shape (6577, 7) >>> data.dropna().shape (6575, 7) # 對部分缺失行進行填充 # 用后一行的值填充前一行的缺失值 >>> data_drop_nan.fillnan(method='backfill') # 對指定列填充指定值 >>> data_drop_na.fillna({'購葯時間':'2018-01-20 星期三', '社保卡號': '1.338953e+07'})
另一個例子(https://blog.csdn.net/wangxingfan316/article/details/79363420),是將price為0的值改為了36:
data['price'][data['price']==0]=None
x = 0 for i in data.columns: for j in range(len(data)): if (data[i].isnull()) [j]: data[i][j]='36' x+=1 print(x)
(2)數據不平衡
首先是SMOTE函數的使用,推薦博文:https://www.cnblogs.com/xyou/p/9075443.html(特詳細)
使用的例子:
from imblearn.over_sampling import SMOTE
#eg1
X_resampled_smote, y_resampled_smote = SMOTE().fit_sample(X, y)
#eg2
over_samples = SMOTE(random_state=1234)
over_samples_X,over_samples_y = over_samples.fit_sample(X_train, y_train)
然后是Borderline-SMOTE(來源:https://www.cnblogs.com/kamekin/p/9824294.html),原始的SMOTE是對所有少數類樣本生成新樣本。而改進的方法則是先根據規則判斷出少數類的邊界樣本,再對這些樣本生成新樣本。
SMOTE函數中的kind參數控制了選擇哪種規則:
borderline1:最近鄰中的隨機樣本與該少數類樣本a來自於不同的類;
borderline2:最近鄰中的隨機樣本可以是屬於任何一個類的樣本;
svm:使用支持向量機分類器產生支持向量然后再生成新的少數類樣本。
實現:
from imblearn.under_sampling
import ClusterCentroids cc = ClusterCentroids(random_state=0) X_resampled, y_resampled = cc.fit_sample(X, y)
(3)重復值處理
(原文:https://blog.csdn.net/maymay_/article/details/80197629 )
pandas 的duplicated可以查看重復值,,duplicated函數用於標記Series中的值、DataFrame中的記錄行是否是重復,重復為True,不重復為False。
語句為:
1 pandas.DataFrame.duplicated(self, subset=None, keep=’first’)
subset:用於識別重復的列標簽或列標簽序列,默認所有列標簽
keep=‘frist’:除了第一次出現外,其余相同的被標記為重復
keep=’last’:除了最后一次出現外,其余相同的被標記為重復
keep=False:所有相同的都被標記為重復
重復值刪除:
pandas 里面 drop_duplicates 、drop_duplicates函數用於刪除Series、DataFrame中重復記錄,並返回刪除重復后的結果
pandas.DataFrame.drop_duplicates(self, subset=None, keep=’first’, inplace=False)
pandas.Series.drop_duplicates(self, keep=’first’, inplace=False)
(4)判斷字符串中是否包含目標字符串
可以用pandas的str.contains 判斷,返回boolean Series
(dataframe.colname.str.contains("somestring")).sum
(5)值替換
可以用map進行映射map(function, iterable, …)會根據提供的函數對指定序列做映射。
第一個參數 function 以參數序列中的每一個元素調用 function 函數,返回包含每次 function 函數返回值的新列表。
dataframe["newcol"] = dataframe.somecol.map{ {"female":0 , "male": 1} )
import numpy as np
data.replace([-999,-1000], np.nan) data.replace({-999: np.nan, -1000:0})
(6)異常值
方法1,異常值的重新賦值
#異常值處理
da = data.values#重新賦值data
#異常值處理,將commments大於200000的數據comments設置為58
cont_clou = len(da)#獲取行數
#遍歷數據進行處理
for i in range(0,cont_clou):
if(data.values[i][3]>200000): #print(data.values[i][3]) da[i][3]='58' #print(da[i][3])
方法二,
特征工程中的RobustScaler
方法,在做數據特征值縮放的時候,它會利用數據特征的分位數分布,將數據根據分位數划分為多段,只取中間段來做縮放,比如只取25%分位數到75%分位數的數據做縮放。這樣減小了異常數據的影響。
優缺點:(1)有堅實的統計學理論基礎,當存在充分的數據和所用的檢驗類型的知識時,這些檢驗可能非常有效;(2)對於多元數據,可用的選擇少一些,並且對於高維數據,這些檢測可能性很差。
(7)數據篩選
利用pandas進行行選擇和列選擇:
import pandas as pd
data = {'state':['Ohio','Ohio','Merry','Nevaio','Nevada'], 'year':[2000,2001,2002,2001,2002], 'pop':[1.5,1.7,3.6,2.4,2.9] } frame = pd.DataFrame(data,columns=['year','state','pop','debt'],index=['one','two','three','four','five'])
找出state中'state'列中含有字符'io'的行,將其的debt列賦值為'aa':
frame.ix[frame['state'].str.contains('io'),['debt']] = 'aa'
也可換個寫法。如state中'state'列中等於‘Ohio’行,將其的debt列賦值為'aa':
frame.ix[frame['state']=='Ohio',['debt']] = 'aa'
多個選擇條件時,用(‘&’、‘|’),如現找出state中'state'列中等於‘Ohio’行或者‘Merry’的行,用'|',將其的debt列賦值為'aa',實現代碼如下:
frame.ix[(frame['state']=='Ohio')|(frame['state']=='Merry'),['debt']] = 'aa'
(8)分箱:
#年齡數據
ages = [20, 22, 25, 27, 21, 23, 37, 31, 61, 45, 41, 32]
# 分箱的邊界
bins = [18, 25, 35, 60, 100] cats = pd.cut(ages, bins) print(type(cats)) # Categorical對象 cats #獲取分箱編碼 cats.codes #返回分箱便捷索引 cats.categories #統計箱中元素的個數 pd.value_counts(cats) #帶標簽的分箱 group_names = ['Youth', 'YoungAdult', 'MiddleAged', 'Senior'] cats = pd.cut(ages, bins, labels = group_names) cats cats.get_values()
還可以借用循環進行分箱
def get_period(row):
hour = row['起飛時間'].hour if hour in range(6,12): return '上午' elif hour in range(12,18): return '下午' else: return '夜間'
(9)啞變量操作
df = pd.DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'b'], 'data1': range(6)}) df pd.get_dummies(df['key'])
二值化數據是通過閾值將數值轉換為二值,大於閾值取值為1,小於閾值取值為0,這個過程又叫二分數據或者閾值轉換。
在生成明確值和特征工程中增加屬性的時候使用。
Python中使用scikit-learn中的Binarizer實現。
from numpy import set_printoptions from sklearn.preprocessing import Binarizer array=data.values X=array[:,0:8]#分離出輸入變量 Y=array[:,8]#分離出輸出變量 transformer=Binarizer(threshold=0.0).fit(X) newX=transformer.transform(X) set_printoptions(precision=3) print(newX.head(10))
(10)向量化字符串操作
data = {'Dave': 'dave@google.com', 'Steve': 'steve@gmail.com', 'Rob': 'rob@gmail.com', 'Wes': np.nan}
data = pd.Series(data)
data
#字符串列元素中是否包含子字符串
data.str.contains('gmail')
#字符串列切片操作
data.str[:5] split_df = data.str.split('@', expand=True) split_df split_df = data.str.split('@') split_df split_df[0].str.cat(split_df[1], sep='@')
(11)衍生變量
pandas使用apply多列生成一列數據的實例:
import pandas as pd
def my_min(a, b): return min(abs(a),abs(b)) s = pd.Series([10.0247,10.0470, 10.0647,10.0761,15.0800,10.0761,10.0647,10.0470,10.0247,10.0,9.9753,9.9530,9.9353,9.9239,18.92,9.9239,9.9353,9.9530,9.9753,10.0]) df = pd.DataFrame(s) df.columns=['value'] df['val_1'] = df['value'].diff() df['val_2'] = df['val_1'].shift(-1) df['val'] = df.apply(lambda row: my_min(row['val_1'], row['val_2']), axis=1)
map和lambda的搭配使用,可以將兩個等長的序列進行運算,生成新的序列。利用這個方法,可以利用DataFrame中已知列的數據生成新列。把col1和col2兩個等長的序列代入了function(x,y)函數,兩列中對應的數據兩兩計算,生成了map對象。再用list()函數把map對象轉化為序列,就可以填入DataFrame生成一個新列new-col了。具體如下:
df['new_col']=list(map(lambda x,y: function(x,y), df['col1'], df['col2']))
(12)調整數據尺度
如果數據的各個屬性按照不同的方式度量數據,就需要調整數據的尺度來讓所有數據按照相同的尺度進行度量,這會給機器學習算法的訓練帶來便利。調整數據尺度通常是將所有的變量進行標准化、或把數據轉換為0和1之間的值,這對於回歸算法、神經網絡及KNN是一種提升准確率的非常有效的方法。在python中,可以用scikit-learm中MinMaxScalar將變量縮小至指定范圍,或者是對數據標准化(均值為0方差為1)。
數據尺度的統一,能夠提高與距離相關算法的准確度。
from numpy import set_printoptions from sklearn.preprocessing import MinMaxScaler array=data.values X=array[:,0:8]#分離出輸入變量 Y=array[:,8]#分離出輸出變量 transformer=MinMaxScaler(feature_range=(0,1))#指定轉換范圍為0到1之間 newX=transformer.fit_transform(X)#數據轉換 set_printoptions(precision=3) print(newX.head(10))
(13)正態化處理
正態化數據是有效的處理符合高斯分布的數據的一種手段,其輸出結果以0為中位數,方差為1,並作為假定數據符合高斯分布的算法的輸入。
適用算法有:線性回歸、邏輯回歸、線性判別分析等。
Python可以通過scikit-learn的StandardScaler。
from numpy import set_printoptions from sklearn.preprocessing import StandardScaler array=data.values X=array[:,0:8]#分離出輸入變量 Y=array[:,8]#分離出輸出變量 transformer=StandardScaler().fit(X) newX=transformer.transform(X) set_printoptions(precision=3) print(newX.head(10))
(14)標准化處理
標准化是指將每一行的數據的距離都處理成1,因此稱為歸一化。適合處理系數數據(比如有很多值都是0)。
標准化對於使用權重輸入的算法,如神經網絡;或者使用距離的算法,如KNN,都具有明顯的准確度提升效果。
Python中是使用scikit-learn中的Normalizer實現。
from numpy import set_printoptions from sklearn.preprocessing import Normalizer array=data.values X=array[:,0:8]#分離出輸入變量 Y=array[:,8]#分離出輸出變量 transformer=Normalizer().fit(X) newX=transformer.transform(X) set_printoptions(precision=3) print(newX.head(10))