用python进行数据分析(二:数据处理)

四、数据处理

(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))

 

posted @ 2019-05-28 14:48  Shilo  阅读(6363)  评论(0编辑  收藏  举报