1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > Python数据清洗-——(1)选择子集 列名重命名;(2)缺失值处理;(3)数据转换(重

Python数据清洗-——(1)选择子集 列名重命名;(2)缺失值处理;(3)数据转换(重

时间:2023-01-20 11:14:00

相关推荐

Python数据清洗-——(1)选择子集 列名重命名;(2)缺失值处理;(3)数据转换(重

:我在这里用的工具是jupyter notebook,代码里面的注释有些挺重要的,大家要仔细看

1、选择子集,列名重命名

在数据分析的过程中,有可能数据量会非常大,但并不是每一列都有分析的 价值,这时候就要从这些数据中选择有用的子集进行分析,或重命名列,这样才能提高分析的价值和效率。此时,我们应该用到列索引

In [1]:import numpy as npIn [2]:import pandas as pdIn [3]: frame2 = pd.DataFrame(data, columns=['year', 'state', 'pop', 'debt'],index=['one', 'two', 'three', 'four', 'five', 'six']) # 创建一矩阵,“index”是行索引, “column”是列索引In [4]: frame2Out[5]:year state pop debtone 2000 Ohio 1.5 NaNtwo 2001 Ohio 1.7 NaNthree 2002 Ohio 3.6 NaNfour 2001 Nevada 2.4 NaNfive 2002 Nevada 2.9 NaNsix003 Nevada 3.2 NaN# 通过类似字典标记的方式或属性的方式,可以将DataFrame的列获取为一个Series# 方式一:In [6]: frame2['state']Out[7]:oneOhiotwoOhiothree Ohiofour Nevadafive NevadasixNevadaName: state, dtype: object# 方式二:In [8]: frame2.yearOut[9]:one2000two2001three 2002four 2001five 2002sixName: year, dtype: int64# 索引多条列In [131]: frame2[['year', 'state']]Out[131]:year state one 2000 Ohio two 2001 Ohio three 2002 Ohio four 2001 Nevada five 2002 Nevada six Nevada # 也可以通过切片获取列或行,重点注意:列(iloc)的切片索引是前闭后开区间(即包括),行(loc)前闭后闭区间In [1]: data = pd.DataFrame(np.arange(16).reshape((4, 4)),index=['Ohio', 'Colorado', 'Utah','New York'], columns=['one', 'two', 'three','four'])# 新建一个随机矩阵,这里涉及到np.arange().reshape()的用法,不了解可以看一下其他博客In [2]: dataOut[2]:one two three fourOhio 012 3Colorado 456 7Utah 891011New York 12 131415# 通过切片获取行In [3]: data[:2]Out[3]:Ohio 012 3Colorado 456 7# 用loc和iloc进行选取,对于DataFrame的行的标签索引,我引入了特殊的标签运算符loc和iloc。它们可以让你用类似NumPy的标记,使用轴标签(loc)或整数索引(iloc),从DataFrame选择行和列的子集。(这 里重点使用iloc)# 们通过标签选择一行和多列:In [4]: data.loc['Colorado', ['two', 'three']]Out[4]:two5three 6Name: Colorado, dtype: int64# 然后用iloc和整数进行选取:In [5]: data.iloc[2, [3, 0, 1]]Out[5]:four 11one 8two 9Name: Utah, dtype: int64In [6]: data.iloc[2]Out[6]:one8two9three 10four 11Name: Utah, dtype: int64In [7]: data.iloc[[1, 2], [3, 0, 1]]Out[7]:four one twoColorado 7 0 5# 这两个索引函数也适用于一个标签或多个标签的切片:In [8]: data.loc[:'Utah', 'two']Out[8]:Ohio0Colorado 5Utah9Name: two, dtype: int64In [9]: data.iloc[:, :3][data.three > 5]Out[9]:one two threeColorado 0 5 6Utah 8 9 10New York 12 13 14# 列的重命名data.rename(columns={‘old_name’:‘new_name’}, inplace = True) #inplace=True是在原df上直接修改

2、缺失值处理

缺失数据在pandas中呈现的方式有些不完美,但对于大多数用户可以保证功能正 常。对于数值数据,pandas使用浮点值NaN(Not a Number)表示缺失数据。我 们称其为哨兵值,可以方便的检测出来,pandas项目中还在不断优化内部细节以更好处理缺失数据,像用户API功能,例如 pandas.isnull,去除了许多恼人的细节。表7-1列出了一些关于缺失数据处理的函 数。

In [1]: data = pd.Series(['aardvark', 'artichoke', np.nan, 'avocado']) # 创建一个series数组In [2]: dataOut[2]:0 aardvark1 artichoke2 NaN3 avocadodtype: objectIn [3]: string_data.isnull() # isnull()查看缺失值,是缺失值返回True,否则返回FalseOut[3]:0 False1 False2 True3 Falsedtype: bool# 处理缺失值常用的两种方法:1、滤除法; 2、替换法(一般使用平均值,众数等替换)# 方法一:滤除法:# 对于DataFrame对象,事情就有点复杂了。你可能希望丢弃全NA或含有NA的行或列。dropna默认丢弃任何含有缺失值的行:In [1]: data = pd.DataFrame([[1., 6.5, 3.], [1., NA, NA],[NA, NA, NA], [NA, 6.5, 3.]])In [2]: cleaned = data.dropna()In [3]: dataOut[3]:0120 1.0 6.5 3.01 1.0 NaN NaN2 NaN NaN NaN3 NaN 6.5 3.0In [4]: cleanedOut[4]:0120 1.0 6.5 3.0# 传入how='all'将只丢弃全为NA的那些行:In [5]: data.dropna(how='all')Out[5]:0120 1.0 6.5 3.01 1.0 NaN NaN3 NaN 6.5 3.0# 用这种方式丢弃列,只需传入axis=1即可:In [6]: data[4] = NA # 添加一列In [7]: dataOut[7]:0 1 2 40 1.0 6.5 3.0 NaN1 1.0 NaN NaN NaN2 NaN NaN NaN NaN3 NaN 6.5 3.0 NaNIn [8]: data.dropna(axis=1, how='all')Out[8]:0 1 20 1.0 6.5 3.01 1.0 NaN NaN2 NaN NaN NaN3 NaN 6.5 3.0# 如果一列的缺失值大于80%,那就删除此列(缺失值大于百分之几删除此列可根据自己的需求所选)In [9]: data[cl] = NA # 添加一列In [10]: dataOut[10]:0 1 2 cl0 1.0 6.5 3.0 NaN1 1.0 NaN NaN NaN2 NaN NaN NaN NaN3 NaN 6.5 3.0 NaNIn [11]:data1 = data.drop(["cl"], axis=1) # 也可以使用 data.drop(columns=["列名"])In [11]:data1Out[12]:0 1 20 1.0 6.5 3.01 1.0 NaN NaN2 NaN NaN NaN3 NaN 6.5 3.0# 删除多列In [13]:data2 = data.drop(["cl", "2"], axis=1) # 也可以使用 data.drop(columns=["列名1","列名2"])In [14]:data2Out[14]:0 1 0 1.0 6.5 1 1.0 NaN 2 NaN NaN 3 NaN 6.5 # 另一个滤除DataFrame行的问题涉及时间序列数据。假设你只想留下一部分观测数据,可以用thresh参数实 现此目的:In [9]: df = pd.DataFrame(np.random.randn(7, 3))In [10]: df.iloc[:4, 1] = NAIn [11]: df.iloc[:2, 2] = NAIn [12]: dfOut[12]:0 1 20 -0.204708 NaNNaN1 -0.555730 NaNNaN2 0.092908 NaN 0.7690233 1.246435 NaN -1.2962214 0.2749920.2289131.3529175 0.886429-2.001637 -0.3718436 1.669025-0.438570 -0.539741In [13]: df.dropna()Out[13]:0 1 24 0.2749920.2289131.3529175 0.886429 -2.001637 -0.3718436 1.669025 -0.438570 -0.539741In [14]: df.dropna(thresh=2)Out[14]:0 1 22 0.092908 NaN 0.7690233 1.246435 NaN-1.2962214 0.2749920.2289131.3529175 0.886429 -2.001637 -0.3718436 1.669025 -0.438570 -0.539741# 方法二:填充缺失数据:# 你可能不想滤除缺失数据(有可能会丢弃跟它有关的其他数据),而是希望通过其他方式填补那些“洞对于大多数情况而言,fillna方法是最主要的函数。通过一个常数调用fillna就会将缺失值替换为那个常数值:In [1]: data = pd.DataFrame([[1., 6.5, 3.], [1., NA, NA],[NA, NA, NA], [NA, 6.5, 3.]])In [2]: dataOut[2]:0120 1.0 6.5 3.01 1.0 NaN NaN2 NaN NaN NaN3 NaN 6.5 3.0# 比如,我们把列名为“1”的列的缺失值(空值)填充,填充值为此列的平均值(最常见的方法)In [3]:mean = np.mean(data["1"])In [4]:meanOut[4]:6.5In [5]:x["1"].fillna(mean, inplace=True)In [6]:dataOut[6]:0120 1.0 6.5 3.01 1.0 6.5 NaN2 NaN 6.5 NaN3 NaN 6.5 3.0

3、数据转换(重复值处理)

(1)重复值: 以下代码表示检测重复值,重复值的处理和之前的缺失值处理差不多,也是采用删除的方法。

# DataFrame中出现重复行有多种原因。下面就是一个例子:In [45]: data = pd.DataFrame({'k1': ['one', 'two'] * 3 + ['two'], 'k2': [1, 1, 2, 3, 3, 4, 4]})In [46]: dataOut[46]:k1k20 one11 two12 one23 two34 one35 two46 two4# DataFrame的duplicated方法返回一个布尔型Series,表示各行是否是重复行(前面出现过的行):In [47]: data.duplicated()Out[47]:0 False1 False2 False3 False4 False5 False6 Truedtype: bool# 还有一个与此相关的drop_duplicates方法,默认情况下,它会根据所有列删除重复的行:In [48]: data1 = data.drop_duplicates()In [49]:data1Out[49]:k1 k20 one 11 two 12 one 23 two 34 one 35 two 4# 要删除特定列上的重复项,请使用subsetIn [50]:data2 = data.drop_duplicates(subest=["k1"])in [51]:data2Out[51]:k1 k20 one 11 two 1

(2)数据转换:对于许多数据集,可能希望根据数组、Series或DataFrame列中的值来实现转换工作,因此可以利用函数或映射进行数据转换

In [52]: data = pd.DataFrame({'food': ['bacon', 'pulled pork', 'bacon','Pastrami', 'corned beef', 'Bacon', 'pastrami', 'honey ham', 'nova lox'],'ounces': [4, 3, 12, 6, 7.5, 8, 3, 5, 6]}) # 建立一组关肉类的数据In [53]: dataOut[53]:foodounces0 bacon 4.01 pulled pork3.02 bacon12.03 Pastrami 6.04 corned beef7.55 Bacon 8.06 pastrami 3.07 honey ham 5.08 nova lox 6.0# 假设我们想要添加一列表示该肉类食物来源的动物类型。我们先编写一个不同肉类到动物的映射:In [54]:meat_to_animal = {'bacon': 'pig', 'pulled pork': 'pig', 'pastrami': 'cow','corned beef': 'cow', 'honey ham': 'pig', 'nova lox': 'salmon'}# Series的map方法可以接受一个函数或含有映射关系的字典型对象,但是这里有一个小问题,即有些肉类的首字母大写了,而另一些则没有。因此,我们还需要使用Series的str.lower方法,将各个值转换为小写:In [55]: lowercased = data['food'].str.lower()In [56]: lowercasedOut[56]:0 bacon1 pulled pork2 bacon3 pastrami4 corned beef5 bacon6 pastrami7 honey ham8 nova loxName: food, dtype: objectIn [57]: data['animal'] = lowercased.map(meat_to_animal)In [58]: dataOut[58]:food ounces animal0 bacon 4.0pig1 pulled pork 3.0pig2 bacon 12.0pig3 Pastrami 6.0cow4 corned beef 7.5cow5 Bacon 8.0pig6 pastrami 3.0cow7 honey ham5.0pig8 nova lox 6.0salmon# 我们也可以传入一个能够完成全部这些工作的函数:In [59]: data['food'].map(lambda x: meat_to_animal[x.lower()])Out[59]:0pig1pig2pig3cow4cow5pig6cow7pig8salmonName: food, dtype: object

4、异常值的处理:这里介绍两种方法(1)3-sigma原则异常值检测;(2)分箱法(四分点检测法),我比较推荐第二种方法

(1)3-sigma原则异常值检测:3-Sigma原则又称为拉依达准则,该准则定义如下:假设一组检测数据只含有随机误差,对原始数据进行计算处理得到标准差,然后按一定的概率确定一个区间,认为误差超过这个区间的就属于异常值。如果数据服从正态分布,异常值被定义为一组测定值中与平均值的偏差超过3倍的值 → p(|x - μ| > 3σ) ≤ 0.003。

特别注意:数据需要服从正态分布,如果数据不服从正态分布,可以用分箱法做异常值处理

代码如下:数据是我随意捏造的,不服从正态分布,有些离谱,但原理不变

In [1]:import numpy as npimport pandas as pd# 创建一组DataFream,在实际应用中一般是提取列(根据自己的需求提取)In [2]:data=pd.DataFrame({'column2'[50,55,60,59,58,69,68,67,798,987,1,2,3,10000,53,63]})Out[2]:column20 501 552 603 594 585 696 687 678 7989 98710 111 212 3131000014 5315 63# 计算平均值In [3]:data_mean = np.mean(data["column2"]) In [4]:data_meanOut[4]:774.5625# 计算方差In [5]:data_std = np.std(data["column2"]) In [6]:data_stdOut[6]:2398.547163616707# 计算正常值的上限In [7]:data_max = data_mean + 3*data_stdIn [8]:data_maxOut[8]:7970.203990850121# 计算正常值的下限In [9]:data_min = data_mean - 3*data_stdIn [10]:data_minOut[10]:-6421.078990850121# 根据loc()函数找出异常值的行索引In [11]:data_new = data.loc[(data['column2']>data_max) | (data['column2']<data_min)]In [12]:data_newOut[12]:column21310000# 通过iloc()函数对异常值进行修改,这里的值是我随便修改的,实际情况根据需求改In [13]:data.iloc[13, :] = [200]In [14]:dataOut[14]:column20 501 552 603 594 585 696 687 678 7989 98710 111 212 313 20014 5315 63

(2)分箱法(四分点检测法):箱形图可以用来观察数据整体的分布情况,利用中位数,25/%分位数,75/%分位数,上边界,下边界等统计量来来描述数据的整体分布情况。通过计算这些统计量,生成一个箱体图,箱体包含了大部分的正常数据,而在箱体上边界和下边界之外的,就是异常数据。

下面这张图是我对四分点检测法的理解:

代码如下:

In [1]:import numpy as npimport pandas as pd# 创建一组DataFream,在实际应用中一般是提取列(根据自己的需求提取)In [2]:data=pd.DataFrame({'column2'[50,55,60,59,58,69,68,67,798,987,1,2,3,10000,53,63]})Out[2]:column20 501 552 603 594 585 696 687 678 7989 98710 111 212 3131000014 5315 63# 计算Q1 计算1/4分位数In [3]:Q1 = np.percentile(data['column2'], 25)In [4]:Q1Out[4]:52.25# 计算Q3 计算3/4分位数In [5]:Q3 = np.percentile(data['column2'], 75)In [6]:Q3Out[6]:68.25# 计算IQR距离In [7]:IQR = Q3 - Q1In [8]:IQROut[8]:16.0# 计算异常值步距In [9]:outlier_step = 1.5 * IQRIn [10]:outlier_stepOut[10]:24.0# 计算上限异常值In [11]:max_limit_box = Q3 + outlier_stepIn [12]:max_limit_boxOut[12]:92.25# 计算下限异常值In [13]:min_limit_box = Q1 - outlier_stepIn [14]:min_limit_boOut[14]:28.25In[15]:print('正常值范围是:'+str(min_limit_box)+'---'+str(max_limit_box))"正常值范围是:28.25---92.25"# 根据loc()函数找出异常值的行索引In [16]:data_new = data.loc[(data['column2'] > max_limit_box) | (data['column2']<min_limit_box)]Out[16]:column28 7989 98710 111 212 31310000# 修改异常值f的方法也是删除或替换,这里就不多家赘述

Python数据清洗-——(1)选择子集 列名重命名;(2)缺失值处理;(3)数据转换(重复值等);(4)异常值的处理

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。