学习目标

掌握pandas读写数据
掌握基本的数据清洗方法
掌握基本的数据整理方法

pandas读写数据

pandas常用的读写不同格式文件的函数表

读取函数 写入函数 描述
read_csv() to_csv() 读写csv格式的数据
read_table() 读取普通分隔符分隔的数据
read_excel() to_excel() 读写excel格式的数据
read_json() to_json() 读写json格式的数据
read_html() to_html() 读写html格式的数据
read_sql() to_sql() 读写数据库中的数据

读写csv文件

读取csv文件中的数据

student.csv文件内容如下:
Name,Math,Physics,Chemistry
WangLi,93,88,90
ZhangHua,97,86,92
LiMing,84,72,77
ZhouBin,97,94,80
这个文件以逗号作为分隔符,可使用pandas的read_csv()函数读取它的内容,返回DataFrame格式的文件。

  1. import pandas as pd
  2. # 从csv中读取数据
  3. csvframe = pd.read_csv('student.csv')
  4. print(csvframe)
  5. '''
  6. Name Math Physics Chemistry
  7. 0 WangLi 93 88 90
  8. 1 ZhangHua 97 86 92
  9. 2 LiMing 84 72 77
  10. 3 ZhouBin 97 94 80
  11. '''

csv文件中的数据为列表数据,位于不同列的元素用逗号隔开,csv文件被视为文本文件,也可以使用pandas的read_table()函数读取,但需要指定分隔符。

  1. pd.read_table('student.csv', sep = ',')
  2. print(csvframe)
  3. '''
  4. Name Math Physics Chemistry
  5. 0 WangLi 93 88 90
  6. 1 ZhangHua 97 86 92
  7. 2 LiMing 84 72 77
  8. 3 ZhouBin 97 94 80
  9. '''

pd.read_csv(filepath_or_buffer, sep = ',', header = 'infer', names = None, index_col = Noone, usecols = None)
作用:读取csv(逗号分隔)文件到DataFrame对象
说明:

  • filepath_or_buffer:拟要读取的文件的路径
  • sep:其类型是str,默认’,’,用来指定分隔符,csv文件中的分隔符一般为逗号分隔符
  • header:指定第几行作为列名,默认为0(第一行)。如果第一行不是列名,是内容,可以设置header = None,以便不把第一行当做列名。
  • names:用于结果的列名列表,对各列重命名,即添加表头
  • index_col:用作行索引的列编号或列名,可使用index_col = [0, 1]来指定文件中的第1和2列为行索引。
  • usecols:选取某几列,不读取整个文件的内容,如usecols = [1, 2]

header参数可以是一个列表,例如[0, 2],这个列表表示将文件中的这些行作为列标题,介于中间的行将被忽略掉(例如本例中的行号为0、2的行将被作为多级标题出现,行号为1的行将被丢弃,dataframe的数据从行号为3的行开始)。

  1. import pandas as pd
  2. # 从csv中读取数据
  3. csvframe = pd.read_csv('student.csv')
  4. print(csvframe)
  5. # 指定csv文件中的行号为0/2的行为列标题
  6. csvframe = pd.read_csv('student.csv', header = [0, 2])
  7. print(csvframe)
  8. '''
  9. Name Math Physics Chemistry
  10. 0 WangLi 93 88 90
  11. 1 ZhangHua 97 86 92
  12. 2 LiMing 84 72 77
  13. 3 ZhouBin 97 94 80
  14. Name Math Physics Chemistry
  15. ZhangHua 97 86 92
  16. 0 LiMing 84 72 77
  17. 1 ZhouBin 97 94 80
  18. '''

往csv文件写入数据

DataFrame.to_csv(path_or_buf = None, sep = ',', na_rep = '', columns = None, header = True, index = True)
作用:以逗号为分隔将DataFrame对象中的数据写入csv文件中
说明:

  • filepath_or_buffer:拟要写入的文件的路径或对象
  • sep:默认字符’,’,用来指定输出文件的字段分隔符
  • na_rep:字符串,默认’’,缺失数据表示
  • columns:指定要写入文件的列
  • header:是否保存列名,默认为True,保存。如果给定字符串列表,则将其作为列名的别名
  • index:是否保存行索引,默认为True,保存 ```python import pandas as pd import csv df10 = pd.DataFrame([[12, 3, 5], [13, 8, 7], [15, 13, 12], [22, 18, 15]],
    1. index = ['2018-08-01', '2018-08-02', '2018-08-03', '2018-08-04'],
    2. columns = ['book', 'box', 'pen'])
    print(df10) df10.to_csv(‘bbp1.csv’, index = False, header = False) with open(‘bbp1.csv’, newline = ‘’) as csvfile: linereader = csv.reader(csvfile) for row in linereader:
    1. print(','.join(row))

‘’’ book box pen 2018-08-01 12 3 5 2018-08-02 13 8 7 2018-08-03 15 13 12 2018-08-04 22 18 15 12,3,5 13,8,7 15,13,12 22,18,15 ‘’’

  1. <a name="hsfgi"></a>
  2. ## 读取text文件
  3. pandas的函数`read_table()`可读取txt文本文件。<br />格式:`pandas.read_table(filepath_or_buffer, sep = '\t', header = 'infer', names = None, index_col = None, skiprows = None, nrows = None, delim_whitespace = False)`<br />作用:读取以'\t'分隔的文件,返回DataFrame对象<br />说明:
  4. - sep:其类型是str, 用来指定分隔符,默认为制表符,可以是正则表达式
  5. - index_col:指定行索引
  6. - skiprows:用来指定读取时要排除的行
  7. - nrows:从文件中要读取的行数
  8. - dclim_whitespace:dclim_whitespace = True表示用空行来分隔每行
  9. 首先在工作目录下创建名为11.txt的文本文件,其内容如下:<br />C Python Java<br />1 4 5<br />3 3 4<br />4 2 3<br />2 1 1
  10. ```python
  11. import pandas as pd
  12. print(pd.read_table('11.txt'))
  13. '''
  14. C Python Java
  15. 0 1 4 5
  16. 1 3 3 4
  17. 2 4 2 3
  18. 3 2 1 1
  19. '''

读写Excel文件

pandas提供了read_excel()函数来读取Excel文件,用to_excel()函数往Excel文件写入数据。
格式:pandas.read_excel(io, sheet_name = 0, header = 0, names = None, index_col = None, usecols = None, skiprows = None, skip_footer = 0)
作用:读取Excel文件中的数据,返回一个DataFrame对象
说明:

  • io:Excel文件路径,是一个字符串
  • sheet_name:返回指定的sheet(表),如果将sheet_name指定为None,则返回全表;如果需要返回多个表,可以将sheet_name指定为一个列表,例如[‘sheet1’, ‘sheet2’];可以根据sheet的名字字符串或索引来指定所要选取的sheet,例如[0, 1, ‘SEET5’]将返回第一、第二和第五个表,默认返回第一个表。
  • header:指定作为列名的行,默认为0,即取第一行,数据为列名行以下的数据;若数据不含列名,则设定header = None
  • names:指定所生成的DataFrame对象的列的名字,传入一个list数据
  • index_col:指定某列为行索引
  • usecols:通过名字或索引值读取指定的列
  • skiprows:省略指定行数的数据
  • skip_footer:int,默认值为0,读取数据时省略最后int行

首先在工作目录下创建名为chengji.xlsx的Excel文件,Sheet1的内容表所示。
39fe12716be4c421924d862b62bc050.jpg

  1. # 将chengji.xlsx的列名作为所生成的DataFrame对象的第一行数据,并重新生成索引
  2. print(pd.read_excel('chengji.xlsx', header = None))

把DataFrame对象df中的数据写入Excel文件的函数为df.to_excel()。
格式:df.to_excel(excel_writer, sheet_name = 'Sheet1', na_rep = '', columns = None, header = True, index = True, index_label = None, startrow = 0, startcol = 0, engine = None)
说明:

  • excel_writer:输出路径
  • sheet_name:将数据存储在Excel的哪个sheet页面,如sheet1页面
  • na_rep:缺失值填充
  • colums:选择输出的列
  • header:指定列名,布尔或字符串列表,默认为True,如果给定字符串列表,则鉴定它是列名称的别名。header = False则不输出题头
  • index:布尔型,默认True,显示行索引(名字),当index = False,则不显示行索引(名字) ```python ‘’’ sheet_name = ‘sheet2’表示将df存储在Wxcel的sheet2页面 columns = [‘course’, ‘grade’]表示选择’course’, ‘grade’两列进行输出 ‘’’

df11 = pd.DataFrame([[‘C’, ‘B’, 32], [‘Java’, ‘A’, 90], [‘Python’, ‘A’, 92], [‘Hadoop’, ‘B’, 88]], columns = [‘course’, ‘grade’, ‘scores’]) df11.to_excel(excel_writer = ‘cgs.xlsx’, sheet_name = ‘sheet2’, columns = [‘course’, ‘grade’])

  1. ![05cb9d9debba1a500563c667bb16412.jpg](https://cdn.nlark.com/yuque/0/2022/jpeg/25684216/1653898451149-30ff1322-8ed3-4240-80de-d0344a976383.jpeg#clientId=u1ca2d2bf-2798-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=316&id=u9e543439&margin=%5Bobject%20Object%5D&name=05cb9d9debba1a500563c667bb16412.jpg&originHeight=289&originWidth=513&originalType=binary&ratio=1&rotation=0&showTitle=false&size=29341&status=done&style=none&taskId=u35448bfb-cc9c-4cd4-a586-f6673a21965&title=&width=560.3999938964844)
  2. <a name="SK0zu"></a>
  3. # 数据预处理
  4. 现实中采集到的原始数据往往不够规范,会存在一定程度的缺失值、重复值以及噪声数据等。直接采用这些的数据进行分析有很大的可能得到错误的结论。因此,在开始数据处理之前,需要对数据进行预处理。<br />垃圾数据会得出垃圾结论
  5. <a name="rJpJN"></a>
  6. ## DataFrame对象的数据预处理方法
  7. | DataFrame对象的数据预处理方法 | 描述 |
  8. | --- | --- |
  9. | df.duplicated(subset = None, keep = 'first') | 针对某些列,返回用布尔序列表示的重复行 |
  10. | df.drop_duplicates(subset = None, keep = 'first', inplace = False) | 用于删除df中重复行,并返回删除重复后的结果 |
  11. | df.fillna(value = None, method = None, axis = None, inplace = False, limit = None) | 使用指定的方法填充NA/NaN缺失值 |
  12. | df.drop(labels = None, axis = 0, index = None, columns = None, inplace = False) | 删除指定轴上的行或列,它不改变原有的DataFrame对象中的数据,而是返回另一个DataFrame对象来存放删除后的数据 |
  13. | df.dropna(axis = 0, how = 'any', thresh = None, subset = None, inpace = False) | 删除指定轴上的缺失值 |
  14. | del df['col'] | 直接在df对象上删除col |
  15. | df.columns = col_lst | 重新命名列名,col_lst为自定义列名列表 |
  16. | df.rename(index = {'row1':'A'}, columns = {'col1':'A1'}) | 重命名行索引名和列索引名 |
  17. | df.reindex(index = None, columns = None, fill_value = 'NaN') | 改变索引,返回一个重新索引的新对象,index用作新行索引,columns用作新列索引,将缺失值填充为fill_value |
  18. | df.replace(to_replace = None, value = None, inplace = False, limit = None, regex = False, method = 'pad') | 用来把to_replace所列出的且在df对象中出现的元素值替换为value所表示的值 |
  19. | df.merge(right, how = 'inner', on = None, left_on = None, right_on = None) | 通过行索引或列索引进行两个DataFrame对象的连接 |
  20. | pandas.concat(objs, axis = 0, join = 'outer', join_axes = None, ignore_index = False, keys = None) | 以指定的轴将多个对象堆叠到一起,concat()不会去重对象中重复的记录 |
  21. | df.stack(level = -1, dropna = True) | df的列旋转成行 |
  22. | df.unstack(level = -1, fill_value = None) | df的行旋转为列 |
  23. <a name="Y5h07"></a>
  24. ## 数据预处理的流程
  25. 数据预处理一般分为三个步骤:数据清洗、数据整理以及数据写入。<br />在数据分析中,数据清洗是数据价值链中最关键的步骤。<br />数据清洗就是处理缺失数据以及清除无意义的信息。对于垃圾数据,即使是通过最好的分析,也将产生错误的结果,并误导业务本身。
  26. <a name="Ka3cK"></a>
  27. ### 数据清洗
  28. 原始数据中因为各种原因,可能存在缺失和错误。一般表现为数据的某些特征缺失,有噪声和不一致。数据清洗过程首先识别出缺失的值,噪声数据和异常数据点等,并纠正数据中的缺失和错误。<br />数据清洗通常包括三个步骤:
  29. - 处理重复值
  30. - 处理缺失值
  31. - 处理异常值
  32. <a name="HVgrE"></a>
  33. #### 查看数据(部分数据)
  34. 查看头部数据,使用`df.head()`会默认打印出前5行。<br />`df.head() # 查看前5行数据,df为DataFrame对象`<br />`df.head(2) # 查看数据前2行数据,括号里指定行数,就会打印指定的前几行数据`<br />查看尾部数据,使用`df.tail()`会默认打印出后5行。<br />`df.tail() # 查看后5行数据,df为DataFrame对象`<br />`df.tail(n) # n为数字几,就是查看尾部几行的数据`
  35. ```python
  36. '''
  37. 数据文件在下方附件中
  38. '''
  39. import pandas as pd
  40. # 读取口罩厂数据,文件路径为根目录
  41. mask_data = pd.read_csv('mask_data.csv')
  42. print(mask_data.head())
  43. print(mask_data.tail())
  44. '''
  45. 订单编号 日期 省 订单量 单价 销售额
  46. 0 87af-48e5-8bed-c5dcf9ecc172 2020-01-01 广东 0.0 30.0 0.0
  47. 1 535a-4eca-8fa0-9cc54c66e11d 2020-01-01 河南 0.0 30.0 0.0
  48. 2 a56d-4415-ad6e-020cdb154c35 2020-01-01 湖北 1.0 30.0 30.0
  49. 3 535a-4eca-8fa0-9cc54c66e11d 2020-01-01 河南 0.0 30.0 0.0
  50. 4 535a-4eca-8fa0-9cc54c66e11d 2020-01-01 河南 0.0 30.0 0.0
  51. 订单编号 日期 省 订单量 单价 \
  52. 101937 6339-43f4-a12b-7b57d1ce3a48 NaN NaN NaN NaN
  53. 101938 5e43-41c2-8696-fd5909cc98a4 NaN NaN 999999999.0 999999999.0
  54. 101939 824c-4f2b-af43-038938d2db46 NaN NaN 999999999.0 999999999.0
  55. 101940 1cf0-483a-ab11-0cebc6406c78 NaN NaN 0.0 NaN
  56. 101941 8318-43df-9d34-0656d9eb759a NaN NaN 0.0 NaN
  57. 销售额
  58. 101937 NaN
  59. 101938 999999999.0
  60. 101939 999999999.0
  61. 101940 0.0
  62. 101941 0.0
  63. '''

代码中所用到的文件:
mask_data.csv
test_data.csv

  1. import pandas as pd
  2. mask_data = pd.read_csv('mask_data.csv')
  3. mask_data

image.png
这份数据存在一些问题,今天我们就先来解决这些问题。
f37337c061406909cac2ac388855001.jpg

重复值处理

重复值很好理解,就跟字面意思一样,指的是表格中重复出现的数据。
处理重复值的方法非常简单,发现重复值,删除即可,这样可以避免重复处理一些不完整的数据。
第十三章 Pandas数据载入与预处理 - 图4
查看重复值:data.duplicated(subset, keep)
作用:返回的是一个存有布尔值的Series对象,如果想查看具体的值,可以直接布尔索引data[data.duplicated(subset, keep)]
说明:

  • subset:可以传入具体的列名或列名序列,来精准定位查看某列的重复值,默认为None
  • keep:可以传入{‘first’, ‘last’, False},默认为’first’,只显示后面出现的重复值。如果要一起显示重复与被重复的数据,可以将keep参数的值设置为False ```python data = {‘name’:[‘Alice’, ‘Jack’, ‘John’, ‘Mary’, ‘Alice’, ‘Jack’, ‘John’, ‘Mary’],
    1. 'age':[40, 10, 30, 20, 40, 10, 30, 20],
    2. 'weight':[65, 30, 50, 40, 65, 30, 50, 40]}
    df = pd.DataFrame(data)

    显示布尔值

    print(df.duplicated())

    当keep为False时,显示所有重复值

    print(df[df.duplicated(keep = False)])

    keep值默认为first,保留第一次出现的值,只显示后面出现的重复值

    print(df[df.duplicated()])

‘’’ 0 False 1 False 2 False 3 False 4 True 5 True 6 True 7 True dtype: bool name age weight 0 Alice 40 65 1 Jack 10 30 2 John 30 50 3 Mary 20 40 4 Alice 40 65 5 Jack 10 30 6 John 30 50 7 Mary 20 40 name age weight 4 Alice 40 65 5 Jack 10 30 6 John 30 50 7 Mary 20 40 ‘’’

  1. 删除重复值:`data.drop_duplicates(subset, keep, inplace)`<br />说明:
  2. - subset:可以传⼊具体的列名或列名序列,来精准定位删除某列的重复值,默认为None
  3. - keep :可以传⼊ {'first', 'last', False},默认为'first' ,保留第⼀次出现的重复值,删除后⾯的重复值
  4. - inplace :可以传⼊ True False,默认为 FalseTrue 表示直接在原来的DataFrame上删除重复项,⽽默认值False表示⽣成⼀个副本
  5. ```python
  6. data = {'name':['Alice', 'Jack', 'John', 'Mary', 'Alice', 'Jack', 'John', 'Mary'],
  7. 'age':[40, 10, 30, 20, 40, 10, 30, 20],
  8. 'weight':[65, 30, 50, 40, 65, 30, 50, 40]}
  9. df = pd.DataFrame(data)
  10. print(df)
  11. # 查看重复数据
  12. print(df[df.duplicated()])
  13. # 去除数据重复值
  14. df.drop_duplicates(inplace = True)
  15. # 验证,重新查看是否有重复值
  16. print(df[df.duplicated(keep = False)])
  17. print(df)
  18. '''
  19. name age weight
  20. 0 Alice 40 65
  21. 1 Jack 10 30
  22. 2 John 30 50
  23. 3 Mary 20 40
  24. 4 Alice 40 65
  25. 5 Jack 10 30
  26. 6 John 30 50
  27. 7 Mary 20 40
  28. name age weight
  29. 4 Alice 40 65
  30. 5 Jack 10 30
  31. 6 John 30 50
  32. 7 Mary 20 40
  33. Empty DataFrame
  34. Columns: [name, age, weight]
  35. Index: []
  36. name age weight
  37. 0 Alice 40 65
  38. 1 Jack 10 30
  39. 2 John 30 50
  40. 3 Mary 20 40
  41. '''

缺失值处理

数据缺失是经常遇到的情况,有一部分是源于现实数据不好获得,一部分则是源于人为因素。
遇到数据缺失的情况,一般有两种方法进行处理:

  • 直接删除
  • 数据填补

直接删除数据是最简便的方法。但这建立在数据量足够多的情况下。此时,删除几个空缺值,对整个数据不会构成较大影响。
查看数据信息:info()
在实际的数据分析项目中,一般使用info()方法查看数据的缺失情况。当非空数据与数据总量不一致时,就说明这份数据有可能存在缺失值。

  1. import pandas as pd
  2. mask_data = pd.read_csv('mask_data.csv')
  3. # 查看mask_data数据的基本信息
  4. mask_data.info()
  5. '''
  6. <class 'pandas.core.frame.DataFrame'>
  7. RangeIndex: 101942 entries, 0 to 101941
  8. Data columns (total 6 columns):
  9. # Column Non-Null Count Dtype
  10. --- ------ -------------- -----
  11. 0 订单编号 101942 non-null object
  12. 1 日期 100956 non-null object
  13. 2 省 100956 non-null object
  14. 3 订单量 100960 non-null float64
  15. 4 单价 100958 non-null float64
  16. 5 销售额 100960 non-null float64
  17. dtypes: float64(3), object(3)
  18. memory usage: 4.7+ MB
  19. '''

dba3a3d513bbad7fd12937795dd53a7.jpg
查看缺失值:data.isnull()
作用:返回DataFrame类型的布尔值数据,检测结果为布尔值,缺失数据会用True来表示,False则代表这里的数据正常。True的位置标示该位置的数据为缺失值。
可以通过data[data.isnull().values]查看具体的值。

  1. data = {'name':['Alice', 'Jack', 'John', 'Mary'],
  2. 'age':[40, 10, None, 20],
  3. 'weight':[65, 30, 50, None]}
  4. df = pd.DataFrame(data)
  5. print(df)
  6. # 返回一个DataFrame类型数据,无法通过data[]索引取值
  7. print(df.isnull())
  8. # 返回一个array数组,可以通过data[]索引取值
  9. print(df.isnull().values)
  10. # 重新查看有空值的数据
  11. df[df.isnull().values]

image.png

  1. import pandas as pd
  2. mask_data = pd.read_csv('mask_data.csv')
  3. # 查看mask_data的缺失值
  4. mask_data.isnull()

image.png

直接删除

删除缺失值:data.dropna(axis, how)
说明:

  • axis:可以传入0或1,0为行,1为列,默认值为0。用于确定是否删除包含缺失值的行或列。
  • how:可以传入’any’或’all’,默认为’any’。’any’表示如果存在任何空值,则删除该行或列;’all’表示如果所有值均为空值,则删除该行或列。

    df.dropna()代码返回的是一个删掉所有缺失数据的DataFrame对象,不会修改原DataFrame对象的数据,因此需要重新赋值给变量来保存结果。 删除所有缺失值后重新赋值给变量mask_data:mask_data = mask_data.dropna()

  1. import pandas as pd
  2. mask_data = pd.read_csv('mask_data.csv')
  3. # 将DataFrame对象中包含缺失值的每一行全部删掉
  4. mask_data = mask_data.dropna()
  5. # 查看mask_data的缺失值
  6. mask_data.isnull()

image.png
df.dropna()将DataFrame对象中包含缺失值的每一行全部删掉。
2589a287ccd3a2c7617ec668e44cc56.jpg
subset参数,它可以在dropna()方法中指定删除一列或多列数据中含有缺失值的行。
将指定的列名写进中括号[]中,再赋值给subset参数,即可限定dropna()方法的删除范围。

  1. # 删除'ID'一列数据缺失的行
  2. test_data = test_data.dropna(subset = ['ID'])

数据填补

缺失值所在的特征为数值型时,通常利用其均值、中位数和众数等描述其集中趋势的统计量来填充;缺失值所在特征为类别型数据时,则选择众数来填充。
填补缺失值:DataFrame.fillna(value = None, method = None, axis = None, inplace = False, limit = None)
说明:

  • value:可以传入变量、字典、Series、DataFrame,用于修改填补缺失值。可以通过字典的形式,针对每一列缺失值进行填补。
  • inplace:可以传入True或False,确认是否在原数据操作。 ```python df = pd.DataFrame([[None, 3, None, None], [2, 4, None, 3],
    1. [None, None, None, None], [0, 1, 5, 4]],
    2. columns = ['A', 'B', 'C', 'D'])
    print(df)

    空值用0填充

    print(df.fillna(0, inplace = False))

    空值用字典填充

    print(df.fillna({‘A’:0, ‘B’:1, ‘C’:2, ‘D’:3}, inplace = False))

‘’’ A B C D 0 NaN 3.0 NaN NaN 1 2.0 4.0 NaN 3.0 2 NaN NaN NaN NaN 3 0.0 1.0 5.0 4.0 A B C D 0 0.0 3.0 0.0 0.0 1 2.0 4.0 0.0 3.0 2 0.0 0.0 0.0 0.0 3 0.0 1.0 5.0 4.0 A B C D 0 0.0 3.0 2.0 3.0 1 2.0 4.0 2.0 3.0 2 0.0 1.0 2.0 3.0 3 0.0 1.0 5.0 4.0 ‘’’

  1. ```python
  2. import numpy as np
  3. import pandas as pd
  4. # 通过字典形式填充缺失值
  5. df = pd.DataFrame(np.random.randn(5, 3))
  6. df.loc[:3, 1] = None
  7. df.loc[:2, 2] = None
  8. print(df)
  9. df.fillna({1:0.88, 2:0.66})

image.png

  1. data = pd.Series([1, None, 3.5, None, 7])
  2. data1 = data.fillna(data.mean())
  3. print(data)
  4. print(data1)
  5. '''
  6. 0 1.0
  7. 1 NaN
  8. 2 3.5
  9. 3 NaN
  10. 4 7.0
  11. dtype: float64
  12. 0 1.000000
  13. 1 3.833333
  14. 2 3.500000
  15. 3 3.833333
  16. 4 7.000000
  17. dtype: float64
  18. '''
  1. df = pd.DataFrame(np.random.randn(4, 3))
  2. df.iloc[2:, 1] = None
  3. df.iloc[3:, 2] = None
  4. print(df)
  5. df[1] = df[1].fillna(df[1].mean())
  6. print(df)
  7. '''
  8. 0 1 2
  9. 0 0.216087 0.500261 -0.074925
  10. 1 -0.472647 -0.915703 1.333018
  11. 2 -0.958768 NaN -2.353904
  12. 3 -0.577112 NaN NaN
  13. 0 1 2
  14. 0 0.216087 0.500261 -0.074925
  15. 1 -0.472647 -0.915703 1.333018
  16. 2 -0.958768 -0.207721 -2.353904
  17. 3 -0.577112 -0.207721 NaN
  18. '''

df.fillna(method = 'ffill')
作用:用前一个数据值替代NaN填补缺失值

  1. import pandas as pd
  2. import numpy as np
  3. df = pd.DataFrame(np.random.randn(6, 3))
  4. df.iloc[2:, 1] = None
  5. df.iloc[4:, 2] = None
  6. print(df)
  7. df.fillna(method = 'ffill')

image.png
df.fillna(method = 'bfill')
作用:用后一个数据值替代NaN,与pad相反,bfill表示用后一个数据代替NaN,可以用limit限制每列可以替代NaN的数目。

  1. import pandas as pd
  2. import numpy as np
  3. df = pd.DataFrame(np.random.randn(6, 3))
  4. df.iloc[2:, 1] = None
  5. df.iloc[4:, 2] = None
  6. print(df)
  7. df.fillna(method = 'bfill')

image.png
df.fillna(df.mean())
作用:用平均数或其他描述性统计量来替代NaN

  1. data = {'name':['Alice', 'Jack', 'John', 'Mary'],
  2. 'math':[76, 85, None, 87],
  3. 'physical':[85, 56, 95, 75],
  4. 'Chinese':[78, None, 85, 58]}
  5. df = pd.DataFrame(data)
  6. print(df)
  7. df.fillna(df.mean())

image.png
常用的缺失值填补:

方法 描述
data.mean() 求平均数
data.median() 求中位数
data.mode() 求众数
data.max() 求最大值
data.min() 最最小值
data.sum() 求和
data.std() 求标准差

strip():清除字符型数据左右(首尾)指定的字符,默认为空格,中间的不清除。

  1. data = {'name':['Alice', 'Jack', 'John', 'Mary'],
  2. 'IP':['221.205.98.55', '183.184.226.205', '221.205.98.55', '222.31.51.200'],
  3. '年龄':[25, 44, 46, 34],
  4. '性别':['女', '男', '男', '女']}
  5. df = pd.DataFrame(data)
  6. print(df)
  7. # 因为IP是一个对象,所以先转为str
  8. newDF = df['IP'].str.strip()
  9. newDF

异常值处理

有时数据中有一个或多个异常大或异常小的数值,超出了这份数据实际的限定范围,这样的数值被称为异常值。
第十三章 Pandas数据载入与预处理 - 图14
df.describe():查看Series对象或者DataFrame对象描述性统计信息

  1. mask_data = pd.read_csv('mask_data.csv')
  2. mask_data.describe()

image.png
2eb1d5b50953f61e8052dece02c29e7.jpg
在pandas库中,有一种筛选数据的方法叫做布尔索引,使用df[]通过表达式的形式来提取一定范围的数据。
使用df['列索引']来提取某一列的信息。
比如想选择mask_data数据中,单价一列小于等于200的数据,就可以设置条件表达式mask_data['单价'] <= 200。把它加入括号中索引:mask_data[mask_data['单价'] <= 200],就可以选取mask_data数据中单价这一列小于等于200的数据。

  1. # 筛选单价小于等于200的数据
  2. mask_data = mask_data[mask_data['单价'] <= 200]
  3. # 查看mask_data的描述性统计信息
  4. mask_data.describe()

image.png

数据整理

数据清洗完毕后并不意味着这份数据可以直接拿去分析。
不光要把数据清洗干净,还需要整理数据将数据变得规整,这样才有利于后续的数据分析。
数据整理指的是在数据分析前对所需字段进行数据排序、数据转换、数据抽取、数据合并、数据计算等准备操作。
7809259ad65976fd8c88e3a07095e2e.jpg
在开始整理数据之前,我们先观察一下清洗好的数据,看看有哪些字段可以被整理。

  1. # 查看之前清洗好的数据
  2. mask_data

image.png
从结果中可以发现,日期这一列数据的格式是年-月-日,也就是说,我们的统计数据是精确到日的。
假设要先分析研究各个月的利润变化情况,所以需要将日期的统计数据由年-月-日调整为月,然后作为新的月份字段保存到数据中。
但是mask_data中的日期列数据并不是datatime类型。

  1. mask_data.info()
  2. '''
  3. <class 'pandas.core.frame.DataFrame'>
  4. Int64Index: 100860 entries, 0 to 100955
  5. Data columns (total 6 columns):
  6. # Column Non-Null Count Dtype
  7. --- ------ -------------- -----
  8. 0 订单编号 100860 non-null object
  9. 1 日期 100860 non-null object
  10. 2 省 100860 non-null object
  11. 3 订单量 100860 non-null float64
  12. 4 单价 100860 non-null float64
  13. 5 销售额 100860 non-null float64
  14. dtypes: float64(3), object(3)
  15. memory usage: 5.4+ MB
  16. '''

Python中有一种专门储存时间日期的数据类型——datetime,可以直接从中提取想要的时间单位。
需要将日期这一列的数据类型转换为datetime类型,才能从中提取月份信息。
因此可以将这次的数据整理分成三个步骤,他们分别是:

  • 转换日期数据
  • 提取月份信息
  • 添加新列

    转换日期数据

    pd.to_datetime(arg, format)
    作用:将DataFrame对象或Series对象的数据类型转换成datetime类型。
    说明:

  • arg:为要转换的数据,它可以是DataFrame对象或Series对象

  • format:为datetime类型的日期格式,比如说这份数据,它是以年-月-日的形式出现的,那么它对应的format就是’%Y-%m-%d’(year-month-day的缩写)

    注意:是datetime而不是datatime,可别写错了哦

  1. import pandas as pd
  2. # 转换日期数据,并设置对应的日期格式
  3. date_data = pd.to_datetime(mask_data['日期'], format = '%Y-%m-%d')
  4. # 查看date_data
  5. date_data
  6. '''
  7. 0 2020-01-01
  8. 1 2020-01-01
  9. 2 2020-01-01
  10. 3 2020-01-01
  11. 4 2020-01-01
  12. ...
  13. 100951 2020-06-30
  14. 100952 2020-06-30
  15. 100953 2020-06-30
  16. 100954 2020-06-30
  17. 100955 2020-06-30
  18. Name: 日期, Length: 100860, dtype: datetime64[ns]
  19. '''

提取月份信息

Series.dt.month:提取月份信息
Series.dt
作用:可以把datetime类型的数据转成便于我们提取对应的日期和时间数据的对象

日期数据属性
s.dt.year 返回年份信息
s.dt.month 返回月份信息
s.dt.day 返回某日信息
  1. # 转换日期数据,并设置对应的日期格式
  2. date_data = pd.to_datetime(mask_data['日期'], format = '%Y-%m-%d')
  3. # 提取日期数据中的月份信息
  4. month_data = date_data.dt.month
  5. # 查看month_data
  6. month_data
  7. '''
  8. 0 1
  9. 1 1
  10. 2 1
  11. 3 1
  12. 4 1
  13. ..
  14. 100951 6
  15. 100952 6
  16. 100953 6
  17. 100954 6
  18. 100955 6
  19. Name: 日期, Length: 100860, dtype: int64
  20. '''

添加新列

df['colname'] = Series
作用:为原数据添加新的一列
说明:

  • df:是DataFrae对象的简称
  • colname:是要添加的新列的列名,在此案例中,colname就是月份
  • Series:是要传入的Series对象

在此案例中,s就是上一页得到的month_data。

  1. mask_data['月份'] = month_data
  2. mask_data

image.png

数据写入

df.to_csv()
作用:将清洗好的数据写入csv文件中
说明:

  • 使用index参数来限制DataFrame对象的行索引是否写入到csv文件。它的默认值为True,会让写入的csv文件包含一列行索引。如果把这个参数设置为index = False就可以取消写入行索引,不用将行索引那一列写入cav文件

    1. # 保存清洗干净的数据,并取消写入行索引
    2. mask_data.to_csv('mask_data_clean.csv', index = False)

    格式问题处理

    格式问题分为格式错误和具体格式处理两种情况:

  • 格式错误:时间、日期、数值等显示格式不一致,比如同一列数值,有的是数字格式、有的是文本格式,这种情况统一成一种格式即可。

  • 具体格式处理:内容中有不该存在的字符,比如某个人的身份证是360199102030022李,此时’李’就是不该存在的字符,这种情况下需要定位修改成正确的身份证号码。

    格式错误

    常见的是时间格式的处理。
    pd.to_datetime(arg, format, errors)
    作用:进行时间格式化
    说明:

  • arg:可以传入需要处理的内容,可以是int、float、str、datetime、list、tuple等。

  • format:传入的值需要对应待处理数据的格式,如’20201201’对应’%Y%m%d’、’11042021’对应’%d%m%Y’.
  • errors:可以传入{‘ignore’, ‘raise’, ‘coerce’},默认为’raise’。如果为’raise’,当无法解析时程序会报错,如20200231,2月没有31号,程序会报错;如果为’coerce’,当无法解析时,将内容设置为空值;如果为’ignore’,当无法解析时,忽视该数据。 ```python result = pd.to_datetime(‘03042021’, format = ‘%d%m%Y’) result

‘’’ Timestamp(‘2021-04-03 00:00:00’) ‘’’

  1. <a name="nLvnY"></a>
  2. #### 具体格式处理
  3. 当数据量过多时,可以通过`data.info()`或`data.dtypes`来查看整体数据的类型,如果某一列的数据都为int类型时,显示的就是int64,如果其中有一个数据是其他类型的话,就会显示object。
  4. ```python
  5. data.info()

当某列数据的类型不符合要求时,可以通过data.astype()进行强制转换。

  1. data['顾客编号'] = data['顾客编号'].astype('object')
  2. data.dtypes

当使用data.astype()遇到报错时,证明该列的数据类型不统一,可以根据报错提示进行定位修正。
862805d809dc69b19ecd43a794f3f86.jpg

常用的数据处理函数

merge数据合并

merge(left, right, how = 'inner', on = None, left_on = None, right_on = None, left_index = False, right_index = False, sort = False, suffixes = ('_x', '_y'), copy = True, indicator = False, validate = None)
作用:通过一个或多个键将两个DataFrame按行合并起来,与SQL中的join用法类似。
说明:

  • left:参与合并的左侧DataFrame
  • right:参与合并的右侧DataFrame
  • how:连接方法有inner、left、right、outer
  • on:用于连接的列名
  • left_on:左侧DataFrame中用于连接键的列
  • right_on:右侧DataFrame中用于连接键的列
  • left_index:左侧DataFrame中行索引作为连接键
  • right_index:右侧DataFrame中行索引作为连接键
  • sort:合并后会对数据排序,默认为True
  • suffixes:修改重复名
    1. price = pd.DataFrame({'fruit':['apple', 'grape', 'orange', 'orange'],
    2. 'price':[8, 7, 9, 11]})
    3. amount = pd.DataFrame({'fruit':['apple', 'grape', 'orange'],
    4. 'amount':[5, 11, 8]})
    5. display(price, amount, pd.merge(price, amount))
    image.png

    concat数据连接

    如果要合并的DataFrame之间没有连接键,就无法使用merge方法。
    pandas中的concat方法可以实现,默认情况下会按行的方向堆叠数据。如果在列向上连接设置axis = 1即可。 ```python s1 = pd.Series([0, 1], index = [‘a’, ‘b’]) s2 = pd.Series([2, 3, 4], index = [‘a’, ‘d’, ‘e’]) s3 = pd.Series([5, 6], index = [‘f’, ‘g’]) print(pd.concat([s1, s2, s3]))

‘’’ a 0 b 1 a 2 d 3 e 4 f 5 g 6 dtype: int64 ‘’’ ```