数据预处理实战(1)


目录

1. 前言
2. 数据字典
3. 优雅使用pandas
  3.1 读取数据
  3.2 索引与选取
  3.3 布尔索引
  3.4 去重
  3.5 分组
  3.6 数据框的合并
    (1)横向合并
    (2)纵向合并
  3.7 排序(ORDER )与替换(REPALCE)
4. 衍生变量与数据编码
  4.1 apply函数
  4.2 map函数
5. 数据描述
6. 数据质量
  6.1 缺失值
  6.2 异常
7. 数据分箱(离散化)


1、前言

数据挖掘的关键在于数据的处理,业间有句话大概就是说模型的特征决定了该模型上限,而参数只是不断接近这个上限而已。还有一句话“机器学习就像中药,而调参就是神农尝百草”,说明调参只是在无数可能性中找出最优(最合适)的一组参数值,不同问题有不同的最优参数,当然我们在考虑最优参数的同时仍要考虑时间成本,也不能说针对某个问题做个模型花了几个月,到那时候可能用户情况又变化了,所以最好的模型就是快狠准。该系列主要记录如何用python的pandas做数据预处理的一些技巧,包括数据质量检查与清洗(缺失与异常值)、数据探索等方面内容。

2、数据字典

|变量 | 定义| 说明|
| :-------------: |:-------------:| : -----:|
|survival | 是否幸存 | 0 = No, 1 = Yes |
|pclass| 船舱等级| 1 = 1st, 2 = 2nd, 3 = 3rd |
|sex | 性别| |
|Age | 年龄| |
|sibsp| 有多少兄弟姐妹一起乘船 | |
|parch|有 多少父母与儿子一起乘船 | |
|ticket| 船票编号| |
|fare | 船票价格| |
|cabin| 舱数量| |
|embarked| 上船地点| C = Cherbourg, Q = Queenstown, S = Southampton|

注:基础数据为:kaggle案例——泰坦尼克号

3、优雅使用pandas

3.1 读取数据

import pandas as pd
df_titanic = pd.read_csv('C:/Users/whenif/Desktop/titanic_train.csv')
原始数据框

3.2 索引与选取

类似SQL的SELECT语句,主要包括以下函数调用:

  • loc——通过行标签索引行数据
  • iloc——通过行号获取行数据
  • ix——结合前两种的混合索引
import copy
df_titanic_tmp = copy.deepcopy(df_titanic.iloc[0:5])#选取前五列作为实验
df_titanic_tmp.index = ['a','b','c','d','e']#修改索引名
df_titanic_tmp.columns
df_titanic_tmp.rename(columns={'PassengerId': 'haha'}, inplace=True)#修改列名名

根据行与列的可能情况做组合,一般的选取有以下四种情况。

#选取某一行所有列
df_titanic_tmp.loc['a']
df_titanic_tmp.iloc[1]
df_titanic_tmp.ix['a']
df_titanic_tmp.ix[1]
#选取某一列所有行
df_titanic_tmp['Survived']
df_titanic_tmp[['Survived','Pclass']]
df_titanic_tmp.loc[:,['Survived']]
df_titanic_tmp.iloc[:,1]
df_titanic_tmp.ix[:,['Survived']]
df_titanic_tmp.ix[:,1]
#选取某一行所有列
df_titanic_tmp.loc['a',:]
df_titanic_tmp.iloc[0,:]
df_titanic_tmp.ix['a',:]
df_titanic_tmp.ix[0,:]
#选取某些列某些行
df_titanic_tmp.loc['a':'c','Survived':'Name']
df_titanic_tmp.iloc[0:2,1:3]
df_titanic_tmp.ix['a':'c','Survived':'Name']
df_titanic_tmp.ix[0:2,1:3]

3.3 布尔索引

类似SQL中的WHERE语句。
实现:基于某些列的条件筛选另一列的值,你会怎么做?

#AND(&)
df_titanic_tmp.loc[(df_titanic_tmp['Survived']==1) 
                    & (df_titanic_tmp['Pclass']>=2)
                    , ['Survived','Pclass','Name']]
#OR(|)
df_titanic_tmp.loc[(df_titanic_tmp['Survived']==1) 
                    | (df_titanic_tmp['Pclass']>=2)
                    , ['Survived','Pclass','Name']]
#IN(isin)/NOT(-)
df_titanic_tmp.loc[-((df_titanic_tmp['Pclass'].isin([1,2])))
                    , ['Survived','Pclass','Name']]
#包含字符串
df_titanic_tmp.loc[(df_titanic_tmp.Name.str.contains('Miss'))
                    , ['Survived','Pclass','Name']]
#取筛选后第一行数据(TOP 1)
df_titanic_tmp.loc[(df_titanic_tmp.Name.str.contains('Miss'))
                    , ['Survived','Pclass','Name']].values[0]

3.4 去重

df_titanic_tmp.drop_duplicates(subset=['Survived'], keep='first', inplace=False).iloc[:,1]
  • subset:为选定的列做distinct,默认为所有列;
  • keep:值选项{'first', 'last', False},保留重复元素中的第一个、最后一个,或全部删除;
  • inplace:默认为False,返回一个新的dataframe;若为True,则返回去重后的原dataframe。

3.5 分组

类似SQL中的GROUP函数。

import numpy as np
df_titanic_tmp.groupby('Survived').size()
df_titanic_tmp.groupby('Survived').count()

df_titanic_tmp.groupby('Survived').agg({'Sex': np.sum})
df_titanic_tmp.groupby('Survived').agg({'Sex': np.max})

df_titanic_tmp.groupby('Survived').agg({'Sex': pd.Series.nunique})

3.6 数据框的合并

类似于SQL中的JOIN模式,可实现左连接、右连接、内连接、全连接等。
(1)横向合并

df_titanic_tmp1 = copy.deepcopy(df_titanic_tmp)
df_titanic_tmp1.rename(columns={'Name': 'Name1'}, inplace=True)
pd.merge(df_titanic_tmp, df_titanic_tmp1, how='left', left_on='Name', right_on='Name1')

(2)纵向合并

pd.concat([df_titanic_tmp,df_titanic_tmp1])

3.7 排序(ORDER )与替换(REPALCE)

df_titanic_tmp.sort_values(['Survived', 'Pclass'], ascending=[False, True])
df_titanic_tmp['Survived'].replace(to_replace=3, value=33, inplace=True)
df_titanic_tmp.replace({'Survived': {3: 33, 4: 44}}, inplace=True)

4、衍生变量与数据编码

4.1 apply函数

df_titanic['Fare2'] = df_titanic['Fare'].apply(
    lambda x: 0 if x <= 0 else x)
def each_len(x):
    return len(x)
print(df_titanic.apply(each_len, axis=0))#axis=0代表函数应用于每一列

4.2 map函数

#女生用1,男生用2表示
sex_mapping = {  
           'female': 1,  
           'male': 2
           } 
df_titanic['Sex'] = df_titanic['Sex'].map(sex_mapping)    

5、数据描述

train_data = df_titanic.iloc[:,[1,2,4,5,6,7,9,11]]
import numpy as np
data_explore = train_data.describe().T
data_explore['null'] = len(train_data)-data_explore['count']#describe自动计算非空值数量

6、数据质量

6.1 缺失值

#直接删除
train_data.dropna()#默认情况下,dropna会删除任何含有缺失值的行
train_data.dropna(how='all') #只删除所有行为缺失值的观测

#用0填补所有缺失值
train_data.fillna(0)

#采用前项填充或后向填充 
train_data.fillna(method='ffill')    #前一个观察值填充 
train_data.fillna(method='bfill')    #前一个观察值填充   

#使用常量填充不同的列或#用均值或中位数填充各自的列
train_data.fillna({'Age':int(train_data['Age'].mean()),'Embarked':3},inplace=True)          

6.2 异常值

def binning(col, cut_points, labels=None):
    minval = col.min()
    maxval = col.max()
    #利用最大值和最小值创建分箱点的列表
    break_points = [minval] + cut_points + [maxval]
    #如果没有标签,则使用默认标签0 ... (n-1)
    if not labels:
        labels = range(len(cut_points)+1)
    #使用pandas的cut功能分箱
    colBin = pd.cut(col,bins=break_points,labels=labels,include_lowest=True)
    return colBin

#为年龄分箱:
cut_points = [30,50,70]
#labels = ["low","medium","high","very high"]
train_data["Age_bin"] = binning(train_data["Age"], cut_points)
print(pd.value_counts(train_data["Age_bin"], sort=False))

7、数据分箱(离散化)

def binning(col, cut_points, labels=None):
  minval = col.min()
  maxval = col.max()
  #利用最大值和最小值创建分箱点的列表
  break_points = [minval] + cut_points + [maxval]
  #如果没有标签,则使用默认标签0 ... (n-1)
  if not labels:
    labels = range(len(cut_points)+1)
  #使用pandas的cut功能分箱
  colBin = pd.cut(col,bins=break_points,labels=labels,include_lowest=True)
  return colBin

#为年龄分箱:
cut_points = [30,50,70]
#labels = ["low","medium","high","very high"]
train_data["Age_bin"] = binning(train_data["Age"], cut_points)
print(pd.value_counts(train_data["Age_bin"], sort=False))

参考与拓展阅读:
[1]Python 拷贝对象(深拷贝deepcopy与浅拷贝copy)
[2]用 Python 做数据处理必看:12 个使效率倍增的 Pandas 技巧(上)
[3]用 Python 做数据处理必看:12 个使效率倍增的 Pandas 技巧(下)
[4]【分析篇】:Pandas像sql操作python 进行数据分析
[5]数据分析之pandas学习


本文所有代码只用于技术交流,拒绝任何商用活动
个人Github
个人博客DebugNLP
欢迎各路同学互相交流

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容