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

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

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

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

In [1]:import numpy as np
In [2]:import pandas as pd

In [3]: frame2 = pd.DataFrame(data, columns=['year', 'state', 'pop', 'debt'],
                               index=['one', 'two', 'three', 'four', 'five', 'six']) 
                                # 创建一矩阵,“index”是行索引, “column”是列索引
In [4]: frame2
Out[5]:
       year  state  pop  debt
one    2000  Ohio   1.5  NaN
two    2001  Ohio   1.7  NaN
three  2002  Ohio   3.6  NaN
four   2001  Nevada 2.4  NaN
five   2002  Nevada 2.9  NaN
six     003  Nevada 3.2  NaN

# 通过类似字典标记的方式或属性的方式,可以将DataFrame的列获取为一个Series
# 方式一:
In [6]: frame2['state']
Out[7]:
one     Ohio
two     Ohio
three   Ohio
four    Nevada
five    Nevada
six     Nevada
Name: state, dtype: object

# 方式二:
In [8]: frame2.year
Out[9]:
one     2000
two     2001
three   2002
four    2001
five    2002
six     2003
Name: 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    2003  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]: data
Out[2]:
           one   two   three   four
Ohio        0     1      2       3
Colorado    4     5      6       7
Utah        8     9     10      11
New York   12    13     14      15

# 通过切片获取行
In [3]: data[:2]
Out[3]:
Ohio        0     1      2       3
Colorado    4     5      6       7

# 用loc和iloc进行选取,对于DataFrame的行的标签索引,我引入了特殊的标签运算符loc和iloc。它们可以
  让你用类似NumPy的标记,使用轴标签(loc)或整数索引(iloc),从DataFrame选择行和列的子集。(这 
  里重点使用iloc)

# 们通过标签选择一行和多列:
In [4]: data.loc['Colorado', ['two', 'three']]
Out[4]:
two     5
three   6
Name: Colorado, dtype: int64

# 然后用iloc和整数进行选取:
In [5]: data.iloc[2, [3, 0, 1]]
Out[5]:
four 11
one  8
two  9
Name: Utah, dtype: int64

In [6]: data.iloc[2]
Out[6]:
one     8
two     9
three  10
four   11
Name: Utah, dtype: int64

In [7]: data.iloc[[1, 2], [3, 0, 1]]
Out[7]:
        four  one  two
Colorado  7    0    5

# 这两个索引函数也适用于一个标签或多个标签的切片:
In [8]: data.loc[:'Utah', 'two']
Out[8]:
Ohio     0
Colorado 5
Utah     9
Name: two, dtype: int64

In [9]: data.iloc[:, :3][data.three > 5]
Out[9]:
          one two three
Colorado   0   5    6
Utah       8   9   10
New 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]: data
Out[2]:
0 aardvark
1 artichoke
2 NaN
3 avocado
dtype: object

In [3]: string_data.isnull() # isnull()查看缺失值,是缺失值返回True,否则返回False
Out[3]:
0 False
1 False
2 True
3 False
dtype: 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]: data
Out[3]:
   0     1     2
0 1.0   6.5   3.0
1 1.0   NaN   NaN
2 NaN   NaN   NaN
3 NaN   6.5   3.0

In [4]: cleaned
Out[4]:
     0     1     2
0   1.0   6.5   3.0

# 传入how='all'将只丢弃全为NA的那些行:
In [5]: data.dropna(how='all')
Out[5]:
   0     1     2
0 1.0   6.5   3.0
1 1.0   NaN   NaN
3 NaN   6.5   3.0

# 用这种方式丢弃列,只需传入axis=1即可:
In [6]: data[4] = NA  # 添加一列
In [7]: data
Out[7]:
    0    1    2    4
0  1.0  6.5  3.0  NaN
1  1.0  NaN  NaN  NaN
2  NaN  NaN  NaN  NaN
3  NaN  6.5  3.0  NaN

In [8]: data.dropna(axis=1, how='all')
Out[8]:
    0    1    2
0  1.0  6.5  3.0
1  1.0  NaN  NaN
2  NaN  NaN  NaN
3  NaN  6.5  3.0

# 如果一列的缺失值大于80%,那就删除此列(缺失值大于百分之几删除此列可根据自己的需求所选)
In [9]: data[cl] = NA  # 添加一列
In [10]: data
Out[10]:
    0    1    2    cl
0  1.0  6.5  3.0  NaN
1  1.0  NaN  NaN  NaN
2  NaN  NaN  NaN  NaN
3  NaN  6.5  3.0  NaN

In [11]:data1 = data.drop(["cl"], axis=1)  # 也可以使用 data.drop(columns=["列名"])
In [11]:data1
Out[12]:
    0    1    2
0  1.0  6.5  3.0
1  1.0  NaN  NaN
2  NaN  NaN  NaN
3  NaN  6.5  3.0

# 删除多列
In [13]:data2 = data.drop(["cl", "2"], axis=1) # 也可以使用 data.drop(columns=["列名1","列名2"])
In [14]:data2
Out[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] = NA
In [11]: df.iloc[:2, 2] = NA
In [12]: df
Out[12]:
        0            1            2
0  -0.204708        NaN          NaN
1  -0.555730        NaN          NaN
2   0.092908        NaN        0.769023
3   1.246435        NaN       -1.296221
4   0.274992      0.228913     1.352917
5   0.886429     -2.001637    -0.371843
6   1.669025     -0.438570    -0.539741

In [13]: df.dropna()
Out[13]:
        0            1            2
4   0.274992     0.228913     1.352917
5   0.886429    -2.001637    -0.371843
6   1.669025    -0.438570    -0.539741

In [14]: df.dropna(thresh=2)
Out[14]:
        0            1            2
2   0.092908        NaN       0.769023
3   1.246435        NaN      -1.296221
4   0.274992     0.228913     1.352917
5   0.886429    -2.001637    -0.371843
6   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]: data
Out[2]:
   0     1     2
0 1.0   6.5   3.0
1 1.0   NaN   NaN
2 NaN   NaN   NaN
3 NaN   6.5   3.0

# 比如,我们把列名为“1”的列的缺失值(空值)填充,填充值为此列的平均值(最常见的方法)
In [3]:mean = np.mean(data["1"])
In [4]:mean
Out[4]:6.5

In [5]:x["1"].fillna(mean, inplace=True)
In [6]:data
Out[6]:
   0     1     2
0 1.0   6.5   3.0
1 1.0   6.5   NaN
2 NaN   6.5   NaN
3 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]: data
Out[46]:
    k1     k2
0  one     1
1  two     1
2  one     2
3  two     3
4  one     3
5  two     4
6  two     4

# DataFrame的duplicated方法返回一个布尔型Series,表示各行是否是重复行(前面出现过的行):
In [47]: data.duplicated()
Out[47]:
0  False
1  False
2  False
3  False
4  False
5  False
6  True
dtype: bool

# 还有一个与此相关的drop_duplicates方法,默认情况下,它会根据所有列删除重复的行:
In [48]: data1 = data.drop_duplicates()
In [49]:data1
Out[49]:
    k1   k2
0  one   1
1  two   1
2  one   2
3  two   3
4  one   3
5  two   4

# 要删除特定列上的重复项,请使用subset
In [50]:data2 = data.drop_duplicates(subest=["k1"])
in [51]:data2
Out[51]:
    k1   k2
0  one   1
1  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]: data
Out[53]:
     food          ounces
0   bacon           4.0
1   pulled pork     3.0
2   bacon          12.0
3   Pastrami        6.0
4   corned beef     7.5
5   Bacon           8.0
6   pastrami        3.0
7   honey ham       5.0
8   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]: lowercased
Out[56]:
0   bacon
1   pulled pork
2   bacon
3   pastrami
4   corned beef
5   bacon
6   pastrami
7   honey ham
8   nova lox
Name: food, dtype: object

In [57]: data['animal'] = lowercased.map(meat_to_animal)
In [58]: data
Out[58]:
    food             ounces            animal
0  bacon              4.0               pig
1  pulled pork        3.0               pig
2  bacon             12.0               pig
3  Pastrami           6.0               cow
4  corned beef        7.5               cow
5  Bacon              8.0               pig
6  pastrami           3.0               cow
7  honey ham          5.0               pig
8  nova lox           6.0               salmon

# 我们也可以传入一个能够完成全部这些工作的函数:
In [59]: data['food'].map(lambda x: meat_to_animal[x.lower()])
Out[59]:
0     pig
1     pig
2     pig
3     cow
4     cow
5     pig
6     cow
7     pig
8     salmon
Name: food, dtype: object

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

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

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

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

In [1]:import numpy as np
       import 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]:
	column2
0	  50
1	  55
2	  60
3	  59
4	  58
5	  69
6	  68
7	  67
8	 798
9	 987
10	   1
11	   2
12	   3
13	10000
14	  53
15	  63

# 计算平均值
In [3]:data_mean = np.mean(data["column2"])    
In [4]:data_mean
Out[4]:
774.5625

# 计算方差
In [5]:data_std = np.std(data["column2"])    
In [6]:data_std
Out[6]:
2398.547163616707

# 计算正常值的上限
In [7]:data_max = data_mean + 3*data_std      
In [8]:data_max
Out[8]:
7970.203990850121

# 计算正常值的下限
In [9]:data_min = data_mean - 3*data_std
In [10]:data_min
Out[10]:
-6421.078990850121

# 根据loc()函数找出异常值的行索引
In [11]:data_new = data.loc[(data['column2']>data_max) | (data['column2']<data_min)]
In [12]:data_new
Out[12]:
   column2
13	10000

# 通过iloc()函数对异常值进行修改,这里的值是我随便修改的,实际情况根据需求改
In [13]:data.iloc[13, :] = [200]
In [14]:data
Out[14]:
	column2
0	  50
1	  55
2	  60
3	  59
4	  58
5	  69
6	  68
7	  67
8	 798
9	 987
10	   1
11	   2
12	   3
13	 200
14	  53
15	  63

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

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

代码如下:

In [1]:import numpy as np
       import 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]:
	column2
0	  50
1	  55
2	  60
3	  59
4	  58
5	  69
6	  68
7	  67
8	 798
9	 987
10	   1
11	   2
12	   3
13	10000
14	  53
15	  63

# 计算Q1 计算1/4分位数
In [3]:Q1 = np.percentile(data['column2'], 25)
In [4]:Q1
Out[4]:
 52.25

# 计算Q3 计算3/4分位数
In [5]:Q3 = np.percentile(data['column2'], 75)
In [6]:Q3
Out[6]:
 68.25

# 计算IQR距离
In [7]:IQR = Q3 - Q1
In [8]:IQR
Out[8]:
 16.0

# 计算异常值步距
In [9]:outlier_step = 1.5 * IQR
In [10]:outlier_step
Out[10]:
 24.0

# 计算上限异常值
In [11]:max_limit_box = Q3 + outlier_step
In [12]:max_limit_box
Out[12]:
 92.25

# 计算下限异常值
In [13]:min_limit_box = Q1 - outlier_step
In [14]:min_limit_bo
Out[14]:
 28.25

In[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]:
	column2
 8	  798
 9	  987
10	    1
11	    2
12	    3
13	10000

# 修改异常值f的方法也是删除或替换,这里就不多家赘述

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林丑丑@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值