mysql缺失值处理方法,[455]pandas.DataFrame基本操作及缺失值处理

查看DataFrame数据及属性

import pandas as pd

df_obj = pd.DataFrame() #创建DataFrame对象

df_obj.dtypes #查看各行的数据格式

df_obj['列名'].astype(int)#转换某列的数据类型

df_obj.head() #查看前几行的数据,默认前5行

df_obj.tail() #查看后几行的数据,默认后5行

df_obj.index #查看索引

df_obj.columns #查看列名

df_obj.values #查看数据值

df_obj.describe() #描述性统计

df_obj.T #转置

df_obj.sort_values(by=['',''])#同上

为DataFrame添加新的属性列

import pandas as pd

import numpy as np

df = pd.DataFrame(np.random.randint(0, 10, (2, 4)), columns=list('ABCD'))

df['total'] = df['A'] + df['B'] + df['C'] + df['D']

# 等价于 df['total'] = df.A + df.B + df.C + df.D

数据类型

df.values ⇒ 返回的是 numpy 下的多维数组; df.column_name.values ⇒ 返回的也是 numpy 下的数组类型; df.dtypes:返回的是各个属性列的类型; df.select_dtypes([np.object]),df.select_dypes([bool])

简单数据统计

统计某一属性可能的取值:df.column_name.unique()

统计出现的次数:df.column_name.value_counts() column_name 对应的是该 DataFrame 中某列的列名;也即 pandas 下的 DataFrame 对象直接支持 点+列名的方式进行索引;

缺失值的处理

所有缺失值字段填充为 0:df.fillna(0),一定要十分注意的一点是,df.fillna() 操作默认(inplace=False)不是 inplace,也即不是对原始 data frame 直接操作修改的,而是创建一个副本,对副本进行修改;

df.fillna(0, inplace=True)df = df.fillna(0)  舍弃那些全行为 NaN 的行,以及全列为 NaN 的行:

df.dropna(axis=[0, 1], how=’all’)  删除某些行和列:

df.drop([], axis=1, inplace=True) ⇒ axis = 1,删除列;df.drop([], axis=0, inplace=True) ⇒ axis = 0,删除行;

首先创建具有缺失值NaN(Not A Number)的CSV(comma-separated values)文件:

import pandas as pd

from io import StringIO

csv_data = '''A,B,C,D

1.0,2.0,3.0,4.0

5.0,6.0,,8.0

0.0,11.0,12.0,'''

df = pd.read_csv(StringIO(csv_data))

删除含缺失值的样本

具体处理方法:

df.isnull()#是缺失值返回True,否则范围False df.isnull().sum()#返回每列包含的缺失值的个数 df.dropna()#直接删除含有缺失值的行 df.dropna(axis = 1)#直接删除含有缺失值的列 df.dropna(how = ‘all’)#只删除全是缺失值的行 df.dropna(thresh = 4)#保留至少有4个缺失值的行 df.dropna(subset = [‘C’])#删除含有缺失值的特定的列

填充缺失值

数值型数值(Numerical Data)

方法一:fillna()函数

df.fillna(0):用0填充 df.fillna(method=‘pad’):用前一个数值填充 df.fillna(df2.mean()):用该列均值填充

均值填充

age_mean = data.Age.mean()

# age_mean = data['Age'].mean()

data.Age[data['Age'].isnull()] = age_mean

# data['Age'] == data.Age 二者是等效的

方法二:Imputer

from sklearn.preprocessing import Imputer

imr = Imputer(missing_values='NaN', strategy='mean', axis=0)#均值填充缺失值

imr = imr.fit(df)

imputed_data = imr.transform(df.values)

DataFrame的基本操作,增、减、改、查

一. 数据选取

从已有的DataFrame中取出其中一列或几列,并对其进行操作。

Pandas取出DataFrame的列有两种方式,两个方式没有好与坏之分,还是看个人喜欢用哪个

#-*- coding:utf-8 -*-

import pandas as pd

df = pd.DataFrame({'goods':['coke cola', 'eggplant','condom'], 'quantity':[12,3,1], 'price':[20,12,80]})

df['goods']     #选择df的goods这一列

df.goods         #同上,是选择列的第二种方法

需要注意的是,第一种方法看似像是一种列表形式,但是如果像是如下方式书写代码会报错

df['goods','quantity']     #会报错,不要妄想通过这种方式获取多列。

上方的形式会引发一个KeyError的错误。如果想通过第一种形式获取多列,正确的形式如下

df[['goods','quantity']]

将多列的列名按照一个list的形式传入,就可以获取一个DataFrame的多列。

二. 数据筛选

往往选取出几个DataFrame的列并不能满足筛选,DataFrame的筛选的形式比较特殊,对列进行筛选时用到的是之前所讲的第二种选取列的形式,有点像是把列名视为一个DataFrame的属性。

#-*- coding:utf-8 -*-

import pandas as pd

df = pd.DataFrame({'goods':['coke cola', 'eggplant','condom'], 'quantity':[12,3,1], 'price':[20,12,80]})

print df[df.goods =='eggplant']

#      goods  price  quantity

# 1  eggplant     12         3

上面代码的意思是选取DataFrame中,goods列的值为’eggplant‘的所有行。DataFrame中也支持多条件筛选,与Python的判断语句相同,and、or、not 和 xor分别代表 和、或、非、抑或。也可以用符号代替 &、|、~、^。每个判断条件要用圆括号括起来,否则会报错

df[(df.goods =='eggplant') & (df.quantity == 12)]

选取df中 goods列值为 eggplant且 对应的 quantity值为12的所有列。

在筛选数据时候也可以使用loc和iloc函数实现子集的选取,意思并不是说上方的筛选语句不对,亲测同样很好用,而且代码简单了点。loc和iloc进行数据筛选的格式如下:

df = df.loc[df.goods=='eggplant', :]

.loc[]相当于是把想要筛选的列通过 ':'全部选出来。loc方法同样支持多条件筛选。

df = df.loc[(df.goods =='eggplant') & (df.quantity == 12), :]

loc形式的多条件筛选,条件与条件之间同样要使用括号分割开。这两行loc方法筛选的结果与之前没用loc方法写的代码效果是一样的,格式规范而言肯定是有loc的更容易让人理解。但是如果只是给自己写脚本完全可以用前一种,必要时候做个注释即可。

条件筛选的另一种形式,就是选取一个DataFrame中满足条件的行的某几列(并不是全部列)。此时只需将上面的代码做一小点改变即可。

df = df.loc[(df.goods =='eggplant') & (df.quantity == 12), ['goods', 'price']]

此时亲测使用loc方式会比较好一些,因为之前loc形式后方的 ‘:’ 代表的是满足条件的全部行的所有列的数据,一个冒号囊括了所有列。此时要是指定其中的某几列,通过list的形式,list的元素是DataFrame的列名,元素类型是字符串。上方的代码所表达的是满足条件的所有行的 goods 和 price 两列。

三. 数据的修改

数据的修改往往有这几种形式

① 针对某个值或者某个范围的值的修改。 ② 增加列、删除列 ③ 增加行、删除行 ④修改索引 ⑤修改列名

数据值的修改常见于分类的问题中,比如将一个列作为分类的列,有时候往往该列的值不是想要的数字表示的不同分类,或者更复杂是一个连续变量,此时针对DataFrame的修改就格外重要。

添加列

df['price'][df.price > 15] = 'expensive'

通过这一行代码,就将df的 price 一列的大于15的商品定义为 ‘expensive’。分类问题中不同的类常常用不同的数字来表示,而不同类之间的转换需要的就是这样的筛选与修改。

增加列的方法很简单,而且很常用,比如想要在之前的df中添加一个叫‘remain’的列,记录是否有货,可以直接使用下面的代码:

df['remain'] = 'yes'

这样就在之前的df后面又加了一列‘remain’,但是这一整列的值为‘yes’。如果不想在末尾加列,而是想在某列之间添加一列,那么就需要使用insert方法。

df.insert(int=0, column = 'remain', value='yes')

int参数传入的是一个整数,这个整数是插入列所在的位置,0代表列的索引为0的位置,也就是第一列。 column参数是设置列名。 value值是给这列赋值,可以是字符串,如果是字符串,那么这一列的值都会是这个字符串;也可以是Pandas的Series,或者是Python的list。这样可以使得这一整列不是同一个值。

删除列

列的删除使用Pandas模块中的drop()方法最为高效。假如要删除刚才添加的remain列。

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

上方这行代码会成功删除DataFrame中的‘remain’列,注意:如果inplace参数不指定为True,只会在内部删除,df并不会被真正改变。axis参数默认是0,也就是代表着行,所以删除列时要把axis改为1。

如果想删除df中多个列,drop()方法也是可以的。

df.drop(labels=['remain', 'quantity'], axis=1, inplace=True)

将想删除的多个列名以Python的列表形式传给labels参数,就可以在该数据框中删除列表中的列。

添加行

Pandas的添加行方式有很多种不过最为直观的方式是这样的

df.loc[3]={'goods':'shampoo','quantity':13, 'price':50}

loc又出现,在索引为3的行(第四行)插入一组数据。数据的形式按照字典的形式传入。还有一种方法是通过append方法。

df = df.append({'goods':'shampoo','quantity':13, 'price':50}, ignore_index=True)

也是使用dict形式传入。

删除行

df.drop(labels = 1, axis=0,inplace = True)

删除索引为1的行,axis=0表示横向删除行。删除多行时,传入labels的参数是一个list,元素是列的索引值。

df.drop(labels = [1, 4, 6], axis=0,inplace = True)

删除df中的索引为1,4,6的行。

修改索引

修改索引有两种情况,改变索引和不改变索引。

① 不改变索引,可以看做是将原始数据按照索引顺序排序

df.sort_index(axis=1,ascending=False)

axis表示所有列都随着索引一起变位置,ascending是降序的意思,默认是False。

② 改变索引

set_index()方法

df.set_index(keys='goods',inplace=True)

将df的goods这一列设置成索引,在原数据框中改。这个方法感觉更适合之前没有索引的情况下。当之前设置了索引的情况下需要的是reindex方法。

df.reindex(new_index,axis=0)

new_index可以是Python列表,元素是现在已有的索引的一部分值,这个方法常常用于保留想留下的行。

修改列名

修改列名需要用到的是rename()方法。

df.rename(columns={'d0': 'rnapol_d0', 'd1': 'rnapol_d1', 'd3': 'rnapol_d3', 'd5': 'rnapol_d5', 'd7': 'rnapol_d7','d11': 'rnapol_d11', 'd15': 'rnapol_d15', 'd18': 'rnapol_d18', 'ipsc': 'rnapol_ipsc'}, inplace=True)

这就是rename改变列名的用法,传入的形式是字典,键值是新名字;value值是原本的列名。这样的好处是做到了一一对应。之后一定要加上inplace参数,设置为TRUE,否则不会在原有的dataframe中改动。

数据类型转化

dataframe中的astype()方法是对数据类型进行转换的函数。以一个例子进行说明

df = pd.DataFrame({'id': range(4), 'age': ['13', '34', '23'], 'weight': ['45.7', '60.9', '55.5']})

df.dtypes

dtype的结果会显示出,id列的数据类型是 int, 而age和weight列的数据类型都是 object。现在将age转化为 int类型,weight转化为float类型。此时astype函数的作用就有所体现。

df.astype({'age':'int', 'weight':'float'})

通过字典的形式传入,将两列转换成了想要的数据类型。

数据排序

dataframe中索引排序用到的是sort_index方法,相似的列数值排序运用的是sort_values()方法。

df.sort_values( by=['age'], ascending=False, inplace=True)  #只通过age进行排序;升序;如有缺失值放在最后。

df.sort_values(by=['age', 'weight'], ascending=True, inplace=True, na_position='first') #先通过age排序,在其基础上通过weight排序;降序,缺失值放在最前方。

数据的排序在实际问题中很有用,比如找出聚类中得分最高的几个项等等。

数据去重

在dataframe中去除重复,使用drop_duplicates()方法。而只是检查dataframe中是否出现重复有的是duplicated方法,如果只是想检查某列中是否存在重复的值可以通过subset参数将列传入到duplicated()方法中。

df.duplicated()  #检查整个dataframe中是否出现重复

df.duplicated(subset='age')  #检查age这列是否出现重复数据

df.drop_duplicates()  #删除dataframe中的重复

其中,subset参数传入的可以是单一的列名;同时也可以是多个列名组成的list。

四. dataframe基本操作

数据抽样

dataframe的抽样直接使用sample()方法进行,抽样在涉及到统计学算法的时候很有用,所以先了解一下这个方法的参数。

df.sample(n=5, replace=False)

df.sample(frac=0.2, replace=True)

这两种是最常用的形式,n参数是直接指定抽多少个样本,frac参数则是一个0到1之间的浮点数,指定的是抽取的样本占多大比例。replace表示是否是有放回的抽取,默认是FALSE。weight参数在这里没体现,这个参数是当样本具有权重时候所用的,weight参数后面加的是列名,未赋值则每列的权重默认为0,如果要赋值权重,所有权重的和为1,如果和不为1,则自动进行归一化处理。

频率统计

dataframe中,统计某列不同的值出现的次数使用value_counts()方法。

df = pd.DataFrame({'id': range(4), 'name': ['Jack', 'Craig', 'Chuck', 'Jack'],'gender': ['M', 'M', 'M', 'F'] , 'age': ['13', '34', '23','4'], 'weight': ['45', '60', '55', '30']})

可以看到上面的dataframe中,name列有重名的,现在要统计不同的名字出现的次数。

df.name.value_counts()

上面的代码反悔的结果是在这个dataframe中,不同的名字出现的次数。

value_counts()方法的一个妙用是用于求占比,假如现在要求的是性别的占比。

df.gender.value_counts()/ sum(df.gender.value_counts)

这行代码返回的是不同性别人数除以总人数所得到的个性别的占比。但是value_counts()方法只能是单变量的计数。如果想设置一个条件后在进行计数,可以使用的是crosstab()方法。

pd.crosstab(index=df.name, columns=df.gender)

这行代码,记录的是不同名字出现的次数,但是将性别分开讨论。columns参数可以传入多个列,传入形式是list,元素是列名。注意:columns传入的列必须是离散型变量,用途是用于分类。

缺失值处理

① 缺失值的检查

检查缺失值所用的函数是isnull(),这看起来和MySQL中的差不多。

print any(df.isnull(), '\n')

检查整个dataframe中是否存在缺失值。

is_null = []

for col in df.columns:

is_null.append(any(pd.isnull(df.col)))

这是检查dataframe每行是否有缺失值。

is_null = []

for index in list(df.index):

is_null.append(any(pd.isnull(df.loc[index, :])))

同理。is_null方法也可以对每列进行缺失值检查。is_null方法返回的是一个布尔值,True表示有缺失值,False表示没有缺失值。

② 缺失值的删除

这是一种比较极端的方法,通过dropna()方法,这个方法的使用有两种形式。

df.dropna()

这种方式是将有缺失值的行全部删除。如果在缺失值较多的情况下,数据的量会大打折扣。

df.dropna('all')

这个是第二种形式,‘all’指明了删除的行是所有值都为缺失值的情况,因为数据中缺失一些数据是很常见的,只删除全部字段都为空的变量才能真正的保留更多的数据。

③ 缺失值的填补

使用fillna()方法可以对dataframe进行缺失值的填补。

df.fillna(0, inplace=True)  #最简单的一种方式,缺失值统一以一个值进行填补

df.fillna(value={'id': 0, 'name': 'No', 'gender': 'unknown', 'age':'unknown', 'weight': 0}, inplace=True)  #针对不同的列设置不同的缺失填补值

df.fillna(method='ffill', inplace=True)  #用上一行的值对自身进行填补

df.fillna(method='bfill', inplace=True)  #用后一行的值对自身进行填补

df.fillna({'age': df.age.mean(), 'weight': df.weight.max()}, inplace=True)  #用不同列的极值,均值,中位数等进行缺失值填补。

数据映射

看见映射,想到的首先是Python中的map()函数,相比于一般的for循环,map函数具有极高的效率。在日常的Python编程中,map()方法所传入的是一个函数和一个序列,这个函数会相继作用于序列中的每一个元素。得到的是一个新的序列。dataframe也是一个特殊的可遍历序列,但是dataframe的映射所用的是apply()方法。

is_null = []

for index in list(df.index):

is_null.append(any(pd.isnull(df.loc[index])))

现在要挑战for循环,将原本的检查每行是否有缺失值的for循环改成apply()形式。

isnull = lambda x : any(pd.isnull(df.loc[x,:]))

is_null = df.apply(func=isnull, axis=1)

func参数是所用的方法,这里的方法是之前设定的lambda函数。axis参数0代表映射到各列,而1代表着映射到每行。

numpy的某些方法也能通过apply()形式作用于dataframe上,比如说现在有一个dataframe里面记录的是学生的各科成绩(第一列到第五列),现在要计算每个学生的均分,和每个科目的中位数。

df['average'] = df.iloc[:, 0:5].apply(func=np.mean, axis=1)

df.iloc[:, 0:5].apply(func=np.median, axis=0)

参考:http://www.cnblogs.com/mtcnn/p/9421730.html https://www.jb51.net/article/137907.htm

你可能感兴趣的:(mysql缺失值处理方法)