2-python数据分析-基于pandas的数据清洗、DataFrame的级联与合并操作

基于pandas的数据清洗

处理丢失数据

  • 有两种丢失数据:
    • None
    • np.nan(NaN)
  • 两种丢失数据的区别
    • None  是对象类型
    • np.nan 是浮点类型
type(None)  # NoneType 对象类型
type(np.nan)  # float 浮点类型 

为什么在数据分析中需要用到的是浮点类型的空而不是对象类型?

  • 数据分析中会常常使用某些形式的运算来处理原始数据,如果原数数据中的空值为NAN的形式,则不会干扰或者中断运算。
  • NAN可以参与运算的
  • None是不可以参与运算

在pandas中如果遇到了None形式的空值则pandas会将其强转成NAN的形式。pandas中,None=nan

pandas处理空值操作

  1. 对空值进行删除
    • 删除我们一般只删除行
  2. 对空值进行填充

主要用的技术点

  • isnull
  • notnull
  • any
  • all
  • dropna
  • fillna

首先创建一组带有空值的数据

df = DataFrame(data=np.random.randint(0,100,size=(7,5)))
df.iloc[2,3] = None
df.iloc[4,2] = np.nan
df.iloc[5,4]= None
df

过滤方式1:对空值进行过滤(删除空所在的行数据)

技术点

  • isnull,any
  • notnull,all
df.isnull()
 

# 哪些行中有空值
# any(axis=1)检测哪些行中存有空值
df.isnull().any(axis=1)  # any会作用isnull返回结果的每一行
# True对应的行就是存有缺失数据的行

0    False
1    False
2     True
3    False
4     True
5     True
6    False
dtype: bool


df.notnull()

df.notnull().all(axis=1)

0     True
1     True
2    False
3     True
4    False
5    False
6     True
dtype: bool

对空值进行过滤

# 将布尔值作为源数据的行索引,只保留True对应的行数据

# 用notnull过滤
df.loc[df.notnull().all(axis=1)]    # 直接保留非Nan的数据
  
# 用istnull过滤
df.loc[df.isnull().any(axis=1)]   # 保留是Nan的数据,不是想要的结果
  
# 先得到是Nan的索引然后,在所有数据中将他们删除
nan_index = df.loc[df.isnull().any(axis=1)].index
df.drop(labels=nan_index, axis=0)
  

过滤方式2:dropna:可以直接将缺失的行或者列进行删除 

df.dropna(axis=0)   # 只要是drop打头,axis所代表的意思一样

对缺失值进行覆盖

  • fillna

# 使用指定值将源数据中所有的空值进行填充
# 通常我们不会这么干,会填充一个有意义的值
df.fillna(value=999)
# 使用空的近邻值进行填充
# method=ffill向前填充,bfill向后填充
df.fillna(axis=0, method='ffill')
 

什么时候用dropna,什么时候用fillna

  • 尽量使用dropna,如果删除成本比较高,则使用fillna

使用空值对应列的均值对空值进行填充

for col in df.columns:
    # 检测哪些列中存有空值
    # df[col].isnull()得到所在列的布尔值,布尔值相加False为0,True为1
    # 若相加后的结果大于0则其中存在True,有空值
    if df[col].isnull().sum() > 0:
        mean_value = df[col].mean()
        df[col] = df[col].fillna(value=mean_value)
 

面试题

  • 数据说明:

    • 数据是1个冷库的温度数据,1-7对应7个温度采集设备,1分钟采集一次。
  • 数据处理目标:

    • 用1-4对应的4个必须设备,通过建立冷库的温度场关系模型,预估出5-7对应的数据。
    • 最后每个冷库中仅需放置4个设备,取代放置7个设备。
    • f(1-4) --> y(5-7)
  • 数据处理过程:

    • 1、原始数据中有丢帧现象,需要做预处理;
    • 2、matplotlib 绘图;
    • 3、建立逻辑回归模型。
  • 无标准答案,按个人理解操作即可,请把自己的操作过程以文字形式简单描述一下,谢谢配合。

  • 测试数据为testData.xlsx

df = pd.read_excel('./testData.xlsx')
df.drop(labels=['none', 'none1'])  # 删掉没用的俩列
 
df.shape   # (1060, 8)

# 删除空对应的行数据
df.dropna(axis=0).shape  # (927, 8)

# 对空值进行填充,这样保证空值被填充
df.fillna(method='ffill',axio=0).fillna(method='bfill',axis=0)
 

处理重复数据

df = DataFrame(data=np.random.randint(0,100,size=(8,6)))
df.iloc[1] = [1,1,1,1,1,1]
df.iloc[3] = [1,1,1,1,1,1]
df.iloc[5] = [1,1,1,1,1,1]
#检测哪些行存有重复的数据
df.duplicated(keep='first') # 保留一行
0    False
1    False
2    False
3     True
4    False
5     True
6    False
7    False
dtype: bool

# 用检查到的布尔值取反做索引取值,得到没有重复的数据
df.loc[~df.duplicated(keep='first')]
 

一步到位删除重复值

df.drop_duplicates(keep='first')  # first是保留第一行重复值
 
df.drop_duplicates(keep='last')  # last是保留最后一行重复值
 
df.drop_duplicates(keep=False)  # False是删除全部重复值

处理异常数据(不符合常规的数据)

  • 自定义一个1000行3列(A,B,C)取值范围为0-1的数据源,然后将C列中的值大于其两倍标准差的异常值进行清洗
df = DataFrame(data=np.random.random(size=(1000,3)),columns=['A','B','C'])
df.head()
# 制定判定异常值的条件
twice_std = df['C'].std() * 2   # 0.5809877730044463

df.loc[~(df['C'] > twice_std)].head()
 

级联操作

  • pd.concat, pd.append

pandas使用pd.concat函数进行级联操作,与numpy中的np.concatenate函数类似,只是多了一些参数

匹配级联

   行列索引都一致的级联叫做匹配级联

df1 = pd.DataFrame(data=np.random.randint(0,100,size=(5,3)),columns=['A','B','C'])
df2 = pd.DataFrame(data=np.random.randint(0,100,size=(5,3)),columns=['A','D','C'])

pd.concat((df1,df1), axis=1)  # axis=0 轴向 列与列级联 , axis=1 横向级联 行和行级联

 不匹配级联

  • 不匹配指的是级联的维度的索引不一致。例如纵向级联时列索引不一致,横向级联时行索引不一致
  • 有2种连接方式:
    • 外连接 outer:补NaN(默认模式),如果想要保留数据的完整性必须使用outer(外连接)
    • 内连接 innter:只连接匹配的项
pd.concat((df1,df2), axis=1)  # 横向级联,没有毛病
 
# concat()中join参数默认是 outer, 会把不能匹配的补Nan
pd.concat((df1,df2),axis=0)
 
# inner 可以把能匹配的匹配,不能匹配的直接不要
pd.concat((df1,df2), axis=0, join='inner')
 

 append函数的使用

  append函数只能轴向级联

df1.append(df1)
df1.append(df1)

合并操作

  • merge与concat的区别在于,merge需要依据某一共同列来进行合并

  • 使用pd.merge()合并时,会自动根据两者相同column名称的那一列,作为key来进行合并。

  • 注意每一列元素的顺序不要求一致

一对一合并

df1 = DataFrame({'employee':['Bob','Jake','Lisa'],
                'group':['Accounting','Engineering','Engineering'],
                })

df2 = DataFrame({'employee':['Lisa','Bob','Jake'],
                'hire_date':[2004,2008,2012],
                })

pd.merge(df1, df2, on='employee') # 参数1:左表,参数2:右边,参数3:on合并条件

一对多合并

df3 = DataFrame({
    'employee':['Lisa','Jake'],
    'group':['Accounting','Engineering'],
    'hire_date':[2004,2016]})
df4 = DataFrame({'group':['Accounting','Engineering','Engineering'],
                       'supervisor':['Carly','Guido','Steve']
                })
pd.merge(df3, df4)  # on如果不写,默认情况下使用两表中共有的列作为合并条件

多对多合并

df5 = DataFrame({'employee':['Bob','Jake','Lisa'],
                 'group':['Accounting','Engineering','Engineering']})

df6 = DataFrame({'group':['Engineering','Engineering','HR'],
                'supervisor':['Carly','Guido','Steve']
                })

pd.merge(df5, df6) # 不指定的话how默认是inner 只将能匹配的合并
 
# 内合并与外合并:outer取并集 inner取交集
pd.merge(df5, df6, how='inner') # inner是只将能匹配的合并
 
pd.merge(df5, df6, how='outer') # outer是能匹配不能匹配的都合并
 
pd.merge(df5, df6, how='right') # right右合并 保留右表数据
 
pd.merge(df5, df6, how='left')  # left左合并 保留左表数据

key的规范化(两张表没有可进行连接的列)

  • 当两张表没有可进行连接的列时,可使用left_on和right_on手动指定merge中左右两边的哪一列列作为连接的列
df7 = DataFrame({'employee':['Bobs','Linda','Bill'],
                'group':['Accounting','Product','Marketing'],
               'hire_date':[1998,2017,2018]})
df8 = DataFrame({'name':['Lisa','Bobs','Bill'],
                'hire_dates':[1998,2016,2007]})
pd.merge(df7, df8, left_on='employee', right_on='name')
原文地址:https://www.cnblogs.com/wgwg/p/13300813.html