数据分析、数据挖掘、可视化是 Python 的众多强项之一,但无论是这几项中的哪一项都必须以数据作为基础。数据通常都存储在外部文件中,例如 txt、csv、excel、数据库。
导入外部数据
导入 xls 或 xlsx 文件
导入 xls 或 xlsx 文件主要使用 Pandas 的 read_excel 方法,语法如下:
pandas.read_excel(io, sheet_name=0, header=0, names=None, index_col=None, usercols=None, squeeze=False, dtype=None, engine=None, converters=None, true_values=None, false_values=None, skiprows=None, nrow=None, na_values=None, keep_default_na=True, verbose=False, parse_dates=False, date_parser=None, thousands=None, comment=None, skipfooter=0, conver_float=True, mangle_dupe_cols=True, **kwds)
常用参数说明:
io: 字符串,xls 或 xlsx 文件路径或类文件对象 sheet_name: None、字符串、整数、字符串列表或整数列表,默认值为0 header: 指定作为列名的行,默认值为0,即取第一行的值为列名。若数据不包含列名,则设置为 header=None names: 默认值为 None,要使用的列名列表 index_col: 指定列为索引列,默认值为 None usercols: int、list 或 字符串,默认值为 None - 如果为 None,则解析所有列 - 如果为 int,则解析最后一列 - 如果为 list 列表,则解析列号、列表的列 - 如果为字符串,则表示以逗号分隔的 Excel 列字母和列范围列表(如,“A:E” 或 “A, C:F”),范围包括双方 squeeze: 布尔值,默认值为False,如果解析的数据只包含一列,则返回一个 Series dtype: 列的数据类型名称或字典,默认值为 None。如,{'a': np.float64} skiprows: 省略指定行数的数据,从第一行开始 skipfooter: 省略指定行数的数据,从尾部数的行开始
序号 | 值 | 说明 |
1 | sheet_name=None | 参数为None,表示获取所有工作表的数据作为 DataFrame 对象 |
2 | sheet_name=0 | 参数为整数,表示索引(即工作表位置)。第一个 Sheet 页中的数据作为 DataFrame 对象 |
3 | sheet_name='Sheet1' | 参数为字符串,表示工作表名称。名为 “Sheet1” 的 Sheet 页中的数据作为 DataFrame 对象 |
4 | sheet_name=[0, 1, 'Sheet3'] | 参数为列表,表示获取多个工作表。第一个、第二个和名为 “Sheet3” 的 Sheet 页中的数据作为 DataFrame 对象 |
- 常规导入
import pandas as pd import os pd.set_option('display.unicode.east_asian_width', True) # 当前工作路径 os.getcwd() df = pd.read_excel(r'../../DataAnalysis/Code/03/12/1月.xlsx') print(df.head()) 买家会员名 买家实际支付金额 收货人姓名 宝贝标题 0 mrhy1 41.86 周某某 零基础学Python 1 mrhy2 41.86 杨某某 零基础学Python 2 mrhy3 48.86 刘某某 零基础学Python 3 mrhy4 48.86 张某某 零基础学Python 4 mrhy5 48.86 赵某某 C#项目开发实战入门
- 导入指定的 Sheet 页
一个 Excel 文件包含多个 Sheet 页,通过设置 sheet_name 参数就可以导入指定 Sheet 页的数据。
import pandas as pd pd.set_option('display.unicode.east_asian_width', True) df = pd.read_excel(r'../../DataAnalysis/Code/03/12/1月.xlsx', sheet_name='莫寒') print(df.head())
- 通过行索引导入指定行列数据
如果通过指定行索引导入 Excel 数据,则需要设置 index_col
参数。
import pandas as pd pd.set_option('display.unicode.east_asian_width', True) # 指定第0列作为行索引 df = pd.read_excel(r'../../DataAnalysis/Code/03/12/1月.xlsx', index_col=0) print(df.head())、 买家实际支付金额 收货人姓名 宝贝标题 买家会员名 mrhy1 41.86 周某某 零基础学Python mrhy2 41.86 杨某某 零基础学Python mrhy3 48.86 刘某某 零基础学Python mrhy4 48.86 张某某 零基础学Python mrhy5 48.86 赵某某 C#项目开发实战入门
- 通过列索引导入指定行列数据
如果通过指定列索引导入 Excel 数据,则需要设置 header
参数。
import pandas as pd pd.set_option('display.unicode.east_asian_width', True) # 指定第1行作为列索引 df = pd.read_excel(r'../../DataAnalysis/Code/03/12/1月.xlsx', header=1) print(df.head()) mrhy1 41.86 周某某 零基础学Python 0 mrhy2 41.86 杨某某 零基础学Python 1 mrhy3 48.86 刘某某 零基础学Python 2 mrhy4 48.86 张某某 零基础学Python 3 mrhy5 48.86 赵某某 C#项目开发实战入门 4 mrhy6 48.86 李某某 C#项目开发实战入门
如果将数据作为列索引,可以设置 header
参数为 None。
import pandas as pd pd.set_option('display.unicode.east_asian_width', True) # 指定数字作为列索引 df = pd.read_excel(r'../../DataAnalysis/Code/03/12/1月.xlsx', header=None) print(df.head()) 0 1 2 3 0 买家会员名 买家实际支付金额 收货人姓名 宝贝标题 1 mrhy1 41.86 周某某 零基础学Python 2 mrhy2 41.86 杨某某 零基础学Python 3 mrhy3 48.86 刘某某 零基础学Python 4 mrhy4 48.86 张某某 零基础学Python
- 导入指定列数据
一个 Excel 表中往往包含多列数据,如果只需要其中的几列,可以通过 usercols
参数指定需要的列,从 0 开始(表示第 1 列,依次类推)。
import pandas as pd pd.set_option('display.unicode.east_asian_width', True) # 导入第一列数据 df = pd.read_excel(r'../../DataAnalysis/Code/03/12/1月.xlsx', usecols=[0]) print(df.head()) 买家会员名 0 mrhy1 1 mrhy2 2 mrhy3 3 mrhy4 4 mrhy5 # 导入多列数据 df = pd.read_excel(r'../../DataAnalysis/Code/03/12/1月.xlsx', usecols=[0, 3]) print(df.head()) 买家会员名 宝贝标题 0 mrhy1 零基础学Python 1 mrhy2 零基础学Python 2 mrhy3 零基础学Python 3 mrhy4 零基础学Python 4 mrhy5 C#项目开发实战入门 # 指定列名称导入多列 df = pd.read_excel(r'../../DataAnalysis/Code/03/12/1月.xlsx', usecols=['买家会员名', '宝贝标题']) print(df.head()) 买家会员名 宝贝标题 0 mrhy1 零基础学Python 1 mrhy2 零基础学Python 2 mrhy3 零基础学Python 3 mrhy4 零基础学Python 4 mrhy5 C#项目开发实战入门
导入 csv 文件
导入 csv 文件时主要使用 Pandas 的 read_csv 方法,语法如下:
pandas.read_csv(filepath_or_buffer, sep=',', delimiter=None, header='infer', names=None, index_col=None, usecols=None, squeeze=False, prefix=None, mangle_dupe_cols=True, dtype=None, engine=None, converters=None, true_values=None, false_values=None, skipinitialspace=False, skiprows=None, nrows=None, na_values=None, keep_default_na=True, na_filter=True, verbose=False, skip_blank_lines=True, parse_dates=False, infer_datetime_format=False, keep_date_col=False, date_parser=None, dayfirst=False, iterator=False, chunksize=None, compression='infer'. thousands=None, decimal=b'.', lineterminator=None, quotechar="", quoting=0, escapechar=None, comment=None, encoding=None)
常用参数说明:
filepath_or_buffer: 字符串,文件路径,也可以是 URL 链接 sep、delimiter: 字符串,分隔符 header: 指定作为列名的行,默认值为0,即取第一行的值为列名。若数据不包含列名,则设置为 header=None names: 默认值为 None,要使用的列名列表 index_col: 指定列为索引列,默认值为 None usercols: int、list 或 字符串,默认值为 None - 如果为 None,则解析所有列 - 如果为 int,则解析最后一列 - 如果为 list 列表,则解析列号、列表的列 - 如果为字符串,则表示以逗号分隔的 Excel 列字母和列范围列表(如,“A:E” 或 “A, C:F”),范围包括双方 squeeze: 布尔值,默认值为False,如果解析的数据只包含一列,则返回一个 Series dtype: 列的数据类型名称或字典,默认值为 None。如,{'a': np.float64} parse_dates: 布尔类型值、int类型值的列表、列表或字典,默认值为False。可以通过parse_dates参数直接将某列转换成datetime64的日期类型。 - parse_dates为True时,尝试解析索引 - parse_dates为int类型值组成的列表时,如[1,2,3],则解析1、2、3列的值作为独立的日期列 - parse_dates为列表组成的列表时,如[[1,3]],则将1、3列合并,作为一个日期列使用 - parse_dates为字典时,如{'总计':[1,3]},则将1、3列合并,合并后的列名为“总计” encoding: 字符串,默认值为None,文件的编码格式 返回值: 返回一个 DataFrame 对象
- 导入 csv 文件
import pandas as pd import os pd.set_option('display.unicode.east_asian_width', True) # 当前工作路径 os.getcwd() df = pd.read_csv(r'../../DataAnalysis/Code/03/16/1月.csv', encoding='gbk') print(df.head()) 买家会员名 买家实际支付金额 收货人姓名 宝贝标题 订单付款时间 0 mrhy1 41.86 周某某 零基础学Python 2018/5/16 9:41 1 mrhy2 41.86 杨某某 零基础学Python 2018/5/9 15:31 2 mrhy3 48.86 刘某某 零基础学Python 2018/5/25 15:21 3 mrhy4 48.86 张某某 零基础学Python 2018/5/25 15:21 4 mrhy5 48.86 赵某某 C#项目开发实战入门 2018/5/25 15:21
Python 常用的编码格式是 UTF-8 和 GBK 格式,默认编码格式为 UTF-8。导入 csv 文件时,需要通过 encoding
参数指定编码格式。
- 指定csv文件的分隔符
import pandas as pd pd.set_option('display.unicode.east_asian_width', True) # 指定csv文件的分隔符 df = pd.read_csv(r'../../DataAnalysis/Code/03/16/1月.csv', sep=',', encoding='gbk') print(df.head())
- 指定列名
import pandas as pd pd.set_option('display.unicode.east_asian_width', True) # 指定列名(默认 header=0 可以省略,表示用第一行作列名) df = pd.read_csv(r'../../DataAnalysis/Code/03/16/1月.csv', header=0, encoding='gbk') print(df.head())
- 导入指定列
import pandas as pd pd.set_option('display.unicode.east_asian_width', True) # 指定列名(默认 header=0 可以省略,表示用第一行作列名) df = pd.read_csv(r'../../DataAnalysis/Code/03/16/1月.csv', usecols=['买家会员名','收货人姓名','宝贝标题'], encoding='gbk') print(df.head()) 买家会员名 收货人姓名 宝贝标题 0 mrhy1 周某某 零基础学Python 1 mrhy2 杨某某 零基础学Python 2 mrhy3 刘某某 零基础学Python 3 mrhy4 张某某 零基础学Python 4 mrhy5 赵某某 C#项目开发实战入门
导入 txt 文本文件
导入 txt 文件同样使用 Pandas 模块的 read_csv 方法,不同的是需要指定 sep 参数(如制表符\t)。read_csv 方法读取 txt 文件后将返回一个 DataFrame 对象。
import pandas as pd pd.set_option('display.unicode.east_asian_width', True) df = pd.read_csv(r'../../DataAnalysis/Code/03/17/1月.txt', sep='\t', encoding='gbk') print(df.head()) 买家会员名 买家实际支付金额 收货人姓名 宝贝标题 订单付款时间 0 mrhy1 41.86 周某某 零基础学Python 2018/5/16 9:41 1 mrhy2 41.86 杨某某 零基础学Python 2018/5/9 15:31 2 mrhy3 48.86 刘某某 零基础学Python 2018/5/25 15:21 3 mrhy4 48.86 张某某 零基础学Python 2018/5/25 15:21 4 mrhy5 48.86 赵某某 C#项目开发实战入门 2018/5/25 15:21
导入 HTML 网页
导入 HTML 网页数据主要使用 Pandas 的 read_html 方法,该方法用于导入带有 table 标签的网页表格数据,语法如下:
pandas.read_html(io, match='.+', flavor=None, header=None, index_col=None, skiprows=None, attrs=None, parse_dates=False, thousands='', encoding=None, decimal='.', converters=None, na_values=None, keep_default_na=True, displayed_only=True)
常用参数说明:
io: 字符串,文件路径或 URL 链接 match: 正则表达式,返回与正则表达式匹配的表格 flavor: 解析器默认为 “lxml” header: 指定列标题所在的行,列表 list 为多重索引 index_col: 指定行标题对应的列,列表 list 为多重索引 encoding: 字符串,默认为 None,文件的编码格式 返回值: 返回一个 DataFrame 对象
使用 read_html 方法前,首先要确定网页表格是否为 table 标签。
import pandas as pd df = pd.DataFrame() url_list = ['http://www.espn.com/nba/salaries/_/seasontype/4'] for i in range(2, 13): url = 'http://www.espn.com/nba/salaries/_/page/%s/seasontype/4' %i url_list.append(url) # 遍历网页中的table标签读取网页表格数据 for url in url_list: df = df.append(pd.read_html(url), ignore_index=True) # 列表解析: 遍历DataFrame对象的第3列,以子字符串$开头 df = df[[x.startswith('$') for x in df[3]]] print(df) # 导出 csv 文件 df.to_csv('NBA.csv', header=['RK', 'NAME', 'TEAM', 'SALARY'], index=False) 0 1 2 3 1 1 Stephen Curry, PG Golden State Warriors $40,231,758 2 2 Chris Paul, PG Oklahoma City Thunder $38,506,482 3 3 Russell Westbrook, PG Houston Rockets $38,506,482 4 4 John Wall, PG Washington Wizards $38,199,000 5 5 Kevin Durant, SF Brooklyn Nets $38,199,000 .. ... ... ... ... 523 476 Nick Young, G Denver Nuggets $1,042,584 524 477 Admiral Schofield, SG Washington Wizards $1,000,000 525 478 Terance Mann, SG LA Clippers $1,000,000 526 479 Ron Baker, G Washington Wizards $948,580 527 480 David Nwaba, SG Brooklyn Nets $903,111
数据抽取
在数据分析过程中,并不是所有的数据都是我们想要的,此时可以抽取部分数据,主要使用 DataFrame 对象中的 loc 属性和 iloc 属性。
-
loc 属性: 以列名和行名作为参数,当只有一个参数时,默认是行名,即抽取整行数据,包括所有列,如 df.loc['A']
-
iloc 属性: 以行和列位置索引(即 0,1,2 ...)作为参数,0 表示第一行;1 表示第二行。当只有一个参数时,默认是行索引,即抽取整行数据,包括所有列,如 df.iloc[0]
抽取行数据
- 抽取一行数据
import pandas as pd data = [[80, None,87, 90], [51, 98, 70], [None, 55, 49, 99], [30, 20, None, 90]] index = ['张三', '李四', '王五', '赵六'] columns = ['语文', '数学', '英语', '物理'] df = pd.DataFrame(data=data, index=index, columns=columns) # 使用loc属性抽取指定行名为“张三”的数据 print(df.loc['张三']) 语文 80.0 数学 NaN 英语 87.0 物理 90.0 Name: 张三, dtype: float64 # 使用iloc属性抽取指定行索引为1的数据 print(df.iloc[1]) 语文 51.0 数学 98.0 英语 70.0 物理 NaN Name: 李四, dtype: float64
- 抽取多行数据
在 loc 属性和 iloc 属性中合理使用冒号 “:”,即可抽取连续任意多行数据。
import pandas as pd data = [[80, None,87, 90], [51, 98, 70], [None, 55, 49, 99], [30, 20, None, 90]] index = ['张三', '李四', '王五', '赵六'] columns = ['语文', '数学', '英语', '物理'] df = pd.DataFrame(data=data, index=index, columns=columns) # 使用loc属性抽取指定行名为“张三”、“王五”的数据 print(df.loc[['张三', '王五']]) 语文 数学 英语 物理 张三 80.0 NaN 87.0 90.0 王五 NaN 55.0 49.0 99.0 # 使用iloc属性抽取指定行索引为1、3的数据 print(df.iloc[[1, 3]]) 语文 数学 英语 物理 李四 51.0 98.0 70.0 NaN 赵六 30.0 20.0 NaN 90.0 # 使用loc属性抽取第一行至指定行名为“王五”的数据 print(df.loc[:'王五':]) 语文 数学 英语 物理 张三 80.0 NaN 87.0 90.0 李四 51.0 98.0 70.0 NaN 王五 NaN 55.0 49.0 99.0 # 使用iloc属性抽取指定行索引为第3行至最后一行的数据 print(df.iloc[2::]) 语文 数学 英语 物理 王五 NaN 55.0 49.0 99.0 赵六 30.0 20.0 NaN 90.0
抽取列数据
- 抽取指定列数据
import pandas as pd data = [[80, None,87, 90], [51, 98, 70], [None, 55, 49, 99], [30, 20, None, 90]] index = ['张三', '李四', '王五', '赵六'] columns = ['语文', '数学', '英语', '物理'] df = pd.DataFrame(data=data, index=index, columns=columns) print(df[['语文', '数学']]) 语文 数学 张三 80.0 NaN 李四 51.0 98.0 王五 NaN 55.0 赵六 30.0 20.0
loc 属性和 iloc 属性都包含了两个参数,第一个参数代表行;第二个参数代表列。注意在抽取指定列数据时, 行参数不能省略。
import pandas as pd data = [[80, None,87, 90], [51, 98, 70], [None, 55, 49, 99], [30, 20, None, 90]] index = ['张三', '李四', '王五', '赵六'] columns = ['语文', '数学', '英语', '物理'] df = pd.DataFrame(data=data, index=index, columns=columns) # 使用loc属性抽取指定列名为“语文”、“数学”的数据 print(df.loc[:, ['语文', '数学']]) 语文 数学 张三 80.0 NaN 李四 51.0 98.0 王五 NaN 55.0 赵六 30.0 20.0 # 使用iloc属性抽取第1列至第3列的数据,但不包括第3列 print(df.iloc[:, :3]) 语文 数学 英语 张三 80.0 NaN 87.0 李四 51.0 98.0 70.0 王五 NaN 55.0 49.0 赵六 30.0 20.0 NaN
- 抽取指定行列数据
import pandas as pd data = [[80, None,87, 90], [51, 98, 70], [None, 55, 49, 99], [30, 20, None, 90]] index = ['张三', '李四', '王五', '赵六'] columns = ['语文', '数学', '英语', '物理'] df = pd.DataFrame(data=data, index=index, columns=columns) # 使用loc属性抽取指定行名为“张三”,列名为“语文”、“数学”的数据 print(df.loc[['张三'], ['语文', '数学']]) 语文 数学 张三 80.0 NaN # 使用iloc属性抽取第2行至最后一行的第1列和第3列的数据 print(df.iloc[1:, [0, 3]]) 语文 物理 李四 51.0 NaN 王五 NaN 99.0 赵六 30.0 90.0
按指定条件抽取数据
使用 DataFrame 对象实现数据查询有以下 3 种方式:
- 取其中的一个元素,如 .iat[x, x]
- 基于位置的查询,如 .iloc[]
- 基于行列名称的查询,如 .loc[x]
import pandas as pd data = [[80, None,87, 90], [51, 98, 70], [None, 55, 49, 99], [30, 20, None, 90]] index = ['张三', '李四', '王五', '赵六'] columns = ['语文', '数学', '英语', '物理'] df = pd.DataFrame(data=data, index=index, columns=columns) # 抽取语文成绩大于70分,英语成绩大于80分的数据 print(df.loc[(df['语文'] > 60) & (df['英语'] > 80)]) 语文 数学 英语 物理 张三 80.0 NaN 87.0 90.0
数据的增、删、改
增加数据
在 DataFrame 对象中增加数据主要包括列数据和行数据的增加。
- 按列增加数据
import pandas as pd data = [[80, None,87, 90], [51, 98, 70], [None, 55, 49, 99], [30, 20, None, 90]] index = ['张三', '李四', '王五', '赵六'] columns = ['语文', '数学', '英语', '物理'] df = pd.DataFrame(data=data, index=index, columns=columns) # 直接为 DataFrame 对象赋值 df['化学'] = [75, None, 59, 90] print(df) 语文 数学 英语 物理 化学 张三 80.0 NaN 87.0 90.0 75.0 李四 51.0 98.0 70.0 NaN NaN 王五 NaN 55.0 49.0 99.0 59.0 赵六 30.0 20.0 NaN 90.0 90.0 # 使用 loc 属性在 DataFrame 对象的最后增加一列 df.loc[:,'历史'] = [81, 70, 90, 93] print(df) 语文 数学 英语 物理 化学 历史 张三 80.0 NaN 87.0 90.0 75.0 81 李四 51.0 98.0 70.0 NaN NaN 70 王五 NaN 55.0 49.0 99.0 59.0 90 赵六 30.0 20.0 NaN 90.0 90.0 93 # 使用 insert 方法在指定位置插入一列 sw = [61, 73, 92, 89] df.insert(5, '生物', sw) print(df) 语文 数学 英语 物理 化学 生物 历史 张三 80.0 NaN 87.0 90.0 75.0 61 81 李四 51.0 98.0 70.0 NaN NaN 73 70 王五 NaN 55.0 49.0 99.0 59.0 92 90 赵六 30.0 20.0 NaN 90.0 90.0 89 93
- 按行增加数据
import pandas as pd pd.set_option('display.unicode.east_asian_width', True) data = [[80, None,87, 90], [51, 98, 70], [None, 55, 49, 99], [30, 20, None, 90]] index = ['张三', '李四', '王五', '赵六'] columns = ['语文', '数学', '英语', '物理'] df = pd.DataFrame(data=data, index=index, columns=columns) # 使用 loc 属性在 DataFrame 对象中增加一行数据 df.loc['小明'] = [100, 90, 95, None] print(df) 语文 数学 英语 物理 张三 80.0 NaN 87.0 90.0 李四 51.0 98.0 70.0 NaN 王五 NaN 55.0 49.0 99.0 赵六 30.0 20.0 NaN 90.0 小明 100.0 90.0 95.0 NaN # 使用字典并结合 append 增加多行数据 df_insert = pd.DataFrame({'语文':[81,85], '数学':[60,90], '英语':[98,71], '物理':[39,75]}, index = ['小红','小芳']) df = df.append(df_insert) print(df) 语文 数学 英语 物理 张三 80.0 NaN 87.0 90.0 李四 51.0 98.0 70.0 NaN 王五 NaN 55.0 49.0 99.0 赵六 30.0 20.0 NaN 90.0 小明 100.0 90.0 95.0 NaN 小红 81.0 60.0 98.0 39.0 小芳 85.0 90.0 71.0 75.0
修改数据
修改数据包括行列标题和数据的修改。
- 修改列标题
import pandas as pd pd.set_option('display.unicode.east_asian_width', True) data = [[80, None,87, 90], [51, 98, 70], [None, 55, 49, 99], [30, 20, None, 90]] index = ['张三', '李四', '王五', '赵六'] columns = ['语文', '数学', '英语', '物理'] df = pd.DataFrame(data=data, index=index, columns=columns) # 直接赋值修改列标题(注意需要将所有的列标题写上) df.columns = ['语文', '数学', '英语', '理综'] print(df) 语文 数学 英语 理综 张三 80.0 NaN 87.0 90.0 李四 51.0 98.0 70.0 NaN 王五 NaN 55.0 49.0 99.0 赵六 30.0 20.0 NaN 90.0 # 通过 rename 方法修改列标题 df.rename(columns={'语文':'语文(上)', '数学':'数学(上)'}, inplace=True) print(df) 语文(上) 数学(上) 英语 理综 张三 80.0 NaN 87.0 90.0 李四 51.0 98.0 70.0 NaN 王五 NaN 55.0 49.0 99.0 赵六 30.0 20.0 NaN 90.0
参数 inplace
为 True,表示直接修改 DataFrame 对象;否则不修改 DataFrame 对象。
- 修改行标题
import pandas as pd pd.set_option('display.unicode.east_asian_width', True) data = [[80, None,87, 90], [51, 98, 70], [None, 55, 49, 99], [30, 20, None, 90]] index = ['张三', '李四', '王五', '赵六'] columns = ['语文', '数学', '英语', '物理'] df = pd.DataFrame(data=data, index=index, columns=columns) # 将行标题统一修改为数字编号 df.index = list(range(0,4)) print(df) 语文 数学 英语 物理 0 80.0 NaN 87.0 90.0 1 51.0 98.0 70.0 NaN 2 NaN 55.0 49.0 99.0 3 30.0 20.0 NaN 90.0
- 修改行数据
import pandas as pd pd.set_option('display.unicode.east_asian_width', True) data = [[80, None,87, 90], [51, 98, 70], [None, 55, 49, 99], [30, 20, None, 90]] index = ['张三', '李四', '王五', '赵六'] columns = ['语文', '数学', '英语', '物理'] df = pd.DataFrame(data=data, index=index, columns=columns) # 使用 loc 属性修改整行数据 df.loc['张三'] = [80, 70, None, 90] df.loc['张三'] = df.loc['张三'] - 10 print(df) 语文 数学 英语 物理 张三 70.0 60.0 NaN 80.0 李四 51.0 98.0 70.0 NaN 王五 NaN 55.0 49.0 99.0 赵六 30.0 20.0 NaN 90.0 # 使用 iloc 属性修改整行数据 df.iloc[1,:] = [55, 80, 100, 93] print(df) 语文 数学 英语 物理 张三 70.0 60.0 NaN 80.0 李四 55.0 80.0 100.0 93.0 王五 NaN 55.0 49.0 99.0 赵六 30.0 20.0 NaN 90.0
- 修改列数据
import pandas as pd pd.set_option('display.unicode.east_asian_width', True) data = [[80, None,87, 90], [51, 98, 70], [None, 55, 49, 99], [30, 20, None, 90]] index = ['张三', '李四', '王五', '赵六'] columns = ['语文', '数学', '英语', '物理'] df = pd.DataFrame(data=data, index=index, columns=columns) # 使用 loc 属性修改整列数据 df.loc[:,'语文'] = [80, 70, None, 90] df.loc['张三'] = df.loc['张三'] - 10 print(df) 语文 数学 英语 物理 张三 70.0 NaN 77.0 80.0 李四 70.0 98.0 70.0 NaN 王五 NaN 55.0 49.0 99.0 赵六 90.0 20.0 NaN 90.0 # 使用 iloc 属性修改整列数据 df.iloc[:,1] = [55, 80, 100, 93] print(df) 语文 数学 英语 物理 张三 70.0 55 77.0 80.0 李四 70.0 80 70.0 NaN 王五 NaN 100 49.0 99.0 赵六 90.0 93 NaN 90.0
- 修改指定行列数据
import pandas as pd pd.set_option('display.unicode.east_asian_width', True) data = [[80, None,87, 90], [51, 98, 70], [None, 55, 49, 99], [30, 20, None, 90]] index = ['张三', '李四', '王五', '赵六'] columns = ['语文', '数学', '英语', '物理'] df = pd.DataFrame(data=data, index=index, columns=columns) # 使用 loc 属性修改行名为“张三”,列名为“语文”的数据 df.loc['张三','语文'] = 100 print(df) 语文 数学 英语 物理 张三 100.0 NaN 87.0 90.0 李四 51.0 98.0 70.0 NaN 王五 NaN 55.0 49.0 99.0 赵六 30.0 20.0 NaN 90.0 # 使用 iloc 属性修改第2行,第3列的数据 df.iloc[1,2] = 60 print(df) 语文 数学 英语 物理 张三 100.0 NaN 87.0 90.0 李四 51.0 98.0 60.0 NaN 王五 NaN 55.0 49.0 99.0 赵六 30.0 20.0 NaN 90.0
删除数据
删除数据主要使用 DataFrame 对象中的 drop 方法,语法如下:
DataFrame.drop(lables=None, axis=0, index=None, columns=None, level=None, inplace=False, errors='raise')
常用参数说明:
lables: 表示行标签或列标签 axis: axis=0,表示按行删除;axis=1,表示按列删除,默认值为0 index: 删除行,默认值为None columns: 删除列,默认值为None level: 针对有两级索引的数据。level=0,表示按第1级索引删除整行;level=1,表示按第2级索引删除整行,默认值为None inplace: 可选参数,对原数组作出修改并返回一个新数组。默认值为False,如果值为True,那么原数组直接就将被替换 errors: 参数为ignore或raise,默认值为raise,如果值为ignore,则取消错误
- 删除行列数据
import pandas as pd pd.set_option('display.unicode.east_asian_width', True) data = [[80, None,87, 90], [51, 98, 70], [None, 55, 49, 99], [30, 20, None, 90]] index = ['张三', '李四', '王五', '赵六'] columns = ['语文', '数学', '英语', '物理'] df = pd.DataFrame(data=data, index=index, columns=columns) # 删除columns为”数学“的列 df.drop(columns='数学', inplace=True) # 删除index为“张三”的行 df.drop(index='张三', inplace=True) print(df) 语文 英语 物理 李四 51.0 70.0 NaN 王五 NaN 49.0 99.0 赵六 30.0 NaN 90.0
import pandas as pd data = { 'one':pd.Series([1,2,3]), 'two':pd.Series([1,2,3,4]), 'three':pd.Series([10,20,30]) } df = pd.DataFrame(data) # 删除columns为”one“的列 df.drop(columns='one', inplace=True) # 删除index为1的行 df.drop(index=1, inplace=True) print(df) two three 0 1 10.0 2 3 30.0 3 4 NaN
- 删除特定条件的行
import pandas as pd pd.set_option('display.unicode.east_asian_width', True) data = [[80, None,87, 90], [51, 98, 70], [None, 55, 49, 99], [30, 20, None, 90]] index = ['张三', '李四', '王五', '赵六'] columns = ['语文', '数学', '英语', '物理'] df = pd.DataFrame(data=data, index=index, columns=columns) # 删除“语文”分数小于60分的所有行 df.drop(index=df[df['语文']<60].index, inplace=True) print(df) 语文 数学 英语 物理 张三 80.0 NaN 87.0 90.0 王五 NaN 55.0 49.0 99.0
数据清洗
查看与处理缺失值
缺失值指的是由于某种原因导致数据为空,这种情况下一般有四种处理方式: 一是不处理;二是删除;三是填充或替换;四是插入值(以均值、中位数、众数等填补)。
- 查看缺失值
使用 DataFrame 对象中的 info 方法,查找缺失值。
import pandas as pd df = pd.read_excel(r'../../DataAnalysis/Code/03/37/TB2018.xls') print(df.info()) <class 'pandas.core.frame.DataFrame'> RangeIndex: 10 entries, 0 to 9 Data columns (total 6 columns): 买家会员名 10 non-null object 买家实际支付金额 10 non-null float64 宝贝总数量 8 non-null float64 宝贝标题 10 non-null object 类别 8 non-null object 订单付款时间 10 non-null datetime64[ns] dtypes: datetime64[ns](1), float64(2), object(3) memory usage: 608.0+ bytes None
在 Python 中,缺失值一般以 NaN 表示,通过 info 方法可以看到“买家会员名”、“买家实际支付金额”、“宝贝标题”和“订单付款时间”的非空数量是10,而“宝贝总数量”和“类别”的非空数量是8,则说明这两项存在空值。
- 判断数据是否存在缺失值
import pandas as pd df = pd.read_excel(r'../../DataAnalysis/Code/03/37/TB2018.xls') print(df.isnull()) 买家会员名 买家实际支付金额 宝贝总数量 宝贝标题 类别 订单付款时间 0 False False False False False False 1 False False False False True False 2 False False False False False False 3 False False True False False False 4 False False False False True False 5 False False False False False False 6 False False False False False False 7 False False True False False False 8 False False False False False False 9 False False False False False False print(df.notnull()) 买家会员名 买家实际支付金额 宝贝总数量 宝贝标题 类别 订单付款时间 0 True True True True True True 1 True True True True False True 2 True True True True True True 3 True True False True True True 4 True True True True False True 5 True True True True True True 6 True True True True True True 7 True True False True True True 8 True True True True True True 9 True True True True True True
- 缺失值删除处理
通过前面的判断得知了数据缺失情况,下面将缺失值删除,主要使用 dropna
方法,该方法用于删除含有缺失值的行。
import pandas as pd df = pd.read_excel(r'../../DataAnalysis/Code/03/37/TB2018.xls') print(df.dropna())
- 缺失值填充处理
DataFrame 对象中的 fillna
函数可以实现填充缺失数据,pad/ffill
函数表示用前一个非缺失值去填充该缺失值;backfill/bfill
函数表示用下一个非缺失值填充该缺失值;None 用于指定一个值去替换该缺失值。
import pandas as pd df = pd.read_excel(r'../../DataAnalysis/Code/03/37/TB2018.xls') # 将NaN填充为0 df['宝贝总数量'] = df['宝贝总数量'].fillna(0) print(df['宝贝总数量']) 0 2.0 1 1.0 2 1.0 3 0.0 4 1.0 5 1.0 6 1.0 7 0.0 8 1.0 9 1.0 Name: 宝贝总数量, dtype: float64
重复值处理
- 判断每一行数据是否重复(完全相同)
import pandas as pd df = pd.read_excel(r'../../DataAnalysis/Code/03/40/1月.xlsx') print(df.duplicated()) 0 False 1 False 2 False 3 True 4 True ... 75 False 76 False 77 False 78 False 79 False Length: 80, dtype: bool
如果返回值为False,表示不重复;返回值为True,表示重复。
- 去除全部的重复数据
df.drop_duplicates()
- 去除指定列的重复数据
df.drop_duplicates(['买家会员名'])
- 保留重复行中的最后一行
df.drop_duplicates(['买家会员名'], keep='last')
- 直接删除,保留一个副本
df.drop_duplicates(['买家会员名','买家支付宝账号'], inplace=False)
异常值的检测与处理
在数据分析中,异常值是指超出或低于正常范围的值,如年龄大于200、身高大于3米等类似数据。主要有如下几种方法来检测异常值:
- 根据给定的数据范围进行判断,不在范围内的数据视为异常值
- 均方差
- 箱型图
了解异常值的检测后,有如下几种方式来处理异常值:
- 最常用的方式是删除
- 将异常值当缺失值处理,以某个值填充
- 将异常值当特殊情况进行分析,研究异常值出现的原因
索引设置
索引的作用
索引的作用相当于图书的目录,可以根据目录中的页码快速找到所需的内容,Pandas 索引的作用如下:
- 更方便地查询数据
- 使用索引可以提升查询性能
- 如果索引是唯一的,Panda 会使用哈希表优化,查找数据的时间复杂度为O(1)
- 如果索引不是唯一的,但是有序,Pandas 会使用二分查找算法,查找数据的时间复杂度为O(logN)
- 如果索引是完全随机的,那么每次查询都要扫描数据表,查找数据的时间复杂度为O(N)
- 强大的数据结构
- 基于分类数的索引,提升性能
- 多维索引,用于 group by 多维聚合结果等
- 时间类型索引,强大的日期和时间的方法支持
重新设置索引
Pandas 有一个很重要的方法是 reindex
,它的作用是创建一个适应新索引的新对象。语法如下:
obj.reindex(lables=None, index=None, column=None, axis=None, method=None, copy=True, fill_value=nan, limit=None, tolerance=None)
常用参数说明:
lables: 标签,可以是数组,默认值为None index: 行索引,默认值为None columns: 列索引,默认值为None axis: 轴,0表示行;1表示列,默认值为None method: 默认值为None,重新设置索引时,选择插入值(用来填充缺失数据)方法,其值可以是None、bfill/backfill(向后填充)、ffill/pad(向前填充)等 fill_value: 缺失值要填充的数据。如缺失值不用NaN填充,用0填充,则设置“fill_value=0”即可
- 对 Series 对象重新设置索引
import pandas as pd s1=pd.Series([88,60,75], index=[1,2,3]) # 重新设置索引,并对缺失值自动填充NaN print(s1.reindex([1,2,3,4,5])) 1 88.0 2 60.0 3 75.0 4 NaN 5 NaN dtype: float64 # 重新设置索引,并对缺失值用0填充 print(s1.reindex([1,2,3,4,5], fill_value=0)) 1 88 2 60 3 75 4 0 5 0 dtype: int64 # 向前填充(和前面数据一样) print(s1.reindex([1,2,3,4,5], method='ffill')) 1 88 2 60 3 75 4 75 5 75 dtype: int64 # 向后填充(和后面数据一样) print(s1.reindex([1,2,3,4,5], method='bfill')) 1 88.0 2 60.0 3 75.0 4 NaN 5 NaN dtype: float64
- 对 DataFrame 对象重新设置索引
对于 DataFrame 对象,reindex 方法用于修改行索引和列索引。
import pandas as pd pd.set_option('display.unicode.east_asian_width', True) data=[[110,105,99], [105,88,115], [109,120,130]] index=['mr001', 'mr003', 'mr005'] columns=['语文', '英语', '数学'] df=pd.DataFrame(data=data, index=index, columns=columns) # 通过reindex方法重新设置行索引 print(df.reindex(['mr001', 'mr002', 'mr003', 'mr004', 'mr005'])) 语文 英语 数学 mr001 110.0 105.0 99.0 mr002 NaN NaN NaN mr003 105.0 88.0 115.0 mr004 NaN NaN NaN mr005 109.0 120.0 130.0 # 通过reindex方法重新设置列索引 print(df.reindex(columns=['语文', '数学', '英语', '物理'])) 语文 数学 英语 物理 mr001 110 99 105 NaN mr003 105 115 88 NaN mr005 109 130 120 NaN # 通过reindex方法重新设置行索引和列索引 print(df.reindex(index=['mr001', 'mr002', 'mr003', 'mr004', 'mr005'], columns=['语文', '数学', '英语', '物理'])) 语文 数学 英语 物理 mr001 110.0 99.0 105.0 NaN mr002 NaN NaN NaN NaN mr003 105.0 115.0 88.0 NaN mr004 NaN NaN NaN NaN mr005 109.0 130.0 120.0 NaN
设置某列为索引
设置某列为行索引主要使用 set_index 方法。
import pandas as pd pd.set_option('display.unicode.east_asian_width', True) df = pd.read_excel(r'../../DataAnalysis/Code/03/12/1月.xlsx') df = df.set_index(['买家会员名']) print(df.head()) 买家实际支付金额 收货人姓名 宝贝标题 买家会员名 mrhy1 41.86 周某某 零基础学Python mrhy2 41.86 杨某某 零基础学Python mrhy3 48.86 刘某某 零基础学Python mrhy4 48.86 张某某 零基础学Python mrhy5 48.86 赵某某 C#项目开发实战入门
重新设置连续的行索引
当我们对 DataFrame 对象进行数据清洗之后,例如,去掉含 NaN 的行之后,发现行索引并没有发生变化。如果需要重新设置索引则可以使用 reset_index
方法。
df = df.dropna().reset_index(drop=True)
数据排序与排名
数据排序
DataFrame 对象数据排序时主要使用 sort_values
方法,该方法类似于 SQL 中的 order by 方法。sort_values
方法可以根据指定行/列进行排序,语法如下:
DataFrame.sort_values(by, axis=0, ascending=True, inplace=False, kind='quicksort', na_position='last', ignore_index=False)
常用参数说明:
by: 要排序的名称列表 axis: 轴,0表示行;1表示列,默认按行排序 ascending: 升序或降序排序,布尔值,指定多个排序可以使用布尔值列表,默认值为True inplace: 布尔值,默认值为False,如果值为True,则就地排序 kind: 指定排序算法,值为'quicksort'、'mergesort'、'heapsort',默认值为'quicksort' na_position: 空值(NaN)的位置,值为'first'则空值在数据开头,值为'last'则空值在数据最后,默认值为'last' ignore_index: 布尔值,是否忽略索引,值为True标记索引(从0开始按顺序的整数值),值为False则忽略索引
- 按一列数据排序
import pandas as pd excel_file = (r'../../DataAnalysis/Code/03/46/mrbook.xlsx') df = pd.DataFrame(pd.read_excel(excel_file)) # 设置数据显示的列数和宽度 pd.set_option('display.max_columns', 500) pd.set_option('display.width', 1000) # 解决数据输出时列名不对齐的问题 pd.set_option('display.unicode.ambiguous_as_wide', True) pd.set_option('display.unicode.east_asian_width', True) # 按“销量”列降序排序 df = df.sort_values(by='销量', ascending=False) print(df.head(10))
- 按多列数据排序
import pandas as pd excel_file = (r'../../DataAnalysis/Code/03/46/mrbook.xlsx') df = pd.DataFrame(pd.read_excel(excel_file)) # 设置数据显示的列数和宽度 pd.set_option('display.max_columns', 500) pd.set_option('display.width', 1000) # 解决数据输出时列名不对齐的问题 pd.set_option('display.unicode.ambiguous_as_wide', True) pd.set_option('display.unicode.east_asian_width', True) # 按“销量”列降序排序,“定价”列升序排序 df = df.sort_values(by=['销量', '定价'], ascending=[False, True]) df.head(10)
- 对分组统计结果排序
import pandas as pd excel_file = (r'../../DataAnalysis/Code/03/46/mrbook.xlsx') df = pd.DataFrame(pd.read_excel(excel_file)) # 设置数据显示的列数和宽度 pd.set_option('display.max_columns', 500) pd.set_option('display.width', 1000) # 解决数据输出时列名不对齐的问题 pd.set_option('display.unicode.ambiguous_as_wide', True) pd.set_option('display.unicode.east_asian_width', True) # 按“类别”分组统计销量并进行降序排序 df = df.groupby(['类别'])['销量'].sum().reset_index() df = df.sort_values(by='销量', ascending=False) print(df) 类别 销量 1 Android 3765 3 C语言C++ 2237 11 Python 1728 6 Java 1024 2 C# 781 10 PHP 602 4 HTML5+CSS3 456 8 Javascript 322 0 ASP.NET 240 9 Oracle 148 7 JavaWeb 129 5 JSP 120 12 SQL 120
- 按行数据排序
按行排序的数据类型要一致,否则会出现错误提示。
dfrow.sort_values(by=0, ascending=True, axis=1)
数据排名
排名是根据 Series 或 DataFrame 对象的某几列的值进行排名,主要使用 rank
方法,语法如下:
obj.rank(axis=0, method='average', numeric_only=None, na_option='keep', ascending=True, pct=False)
常用参数说明:
axis: 轴,0表示行;1表示列,默认按行排名 method: 表示在具有相同值的情况下所使用的排名方法,设置值如下: - average: 默认值,平均排名 - min: 最小值排名 - max: 最大值排名 - first: 按值在原始数据中的出现的顺序分配排名 - dense: 密集排名,类似最小值排名,但是排名每次只增加1,即排名相同的数据只占一个名次 numeric_only: 对于 DataFrame 对象,如果设置值为True,则只对数据列进行排名 na_option: 空值的排名方式 - keep: 保留,将空值等级赋值给NaN值 - top: 如果按升序排序,则将最小排名赋值给NaN值 - bottom: 如果按升序排序,则将最大排名赋值给NaN值 ascending: 升序或降序排序,布尔值,指定多个排序可以使用布尔值列表,默认值为True pct: 布尔值,是否以百分比形式返回排名,默认值为False
- 顺序排名
import pandas as pd excel_file = (r'../../DataAnalysis/Code/03/46/mrbook.xlsx') df = pd.DataFrame(pd.read_excel(excel_file)) # 设置数据显示的列数和宽度 pd.set_option('display.max_columns', 500) pd.set_option('display.width', 1000) # 解决数据输出时列名不对齐的问题 pd.set_option('display.unicode.ambiguous_as_wide', True) pd.set_option('display.unicode.east_asian_width', True) # 按“销量”列降序排序 df = df.sort_values(by='销量', ascending=False) # 顺序排名(对销量相同的产品,按照出现的先后顺序进行排名) df['顺序排名'] = df['销量'].rank(method='first', ascending=False) print(df[['图书名称', '销量', '顺序排名']].head(10))
- 平均排名
# 平均排名(对销量相同的产品,按照顺序排名的平均值进行排名) df['平均排名'] = df['销量'].rank(ascending=False) print(df[['图书名称', '销量', '平均排名']].head(10))
- 最小值排名
import pandas as pd excel_file = (r'../../DataAnalysis/Code/03/46/mrbook.xlsx') df = pd.DataFrame(pd.read_excel(excel_file)) # 设置数据显示的列数和宽度 pd.set_option('display.max_columns', 500) pd.set_option('display.width', 1000) # 解决数据输出时列名不对齐的问题 pd.set_option('display.unicode.ambiguous_as_wide', True) pd.set_option('display.unicode.east_asian_width', True) # 按“销量”列降序排序 df = df.sort_values(by='销量', ascending=False) # 最小值排名(对销量相同的产品,按照顺序排名并取最小值作为排名) df['最小值排名'] = df['销量'].rank(method='min', ascending=False) print(df[['图书名称', '销量', '最小值排名']].head(10))
- 最大值排名
import pandas as pd excel_file = (r'../../DataAnalysis/Code/03/46/mrbook.xlsx') df = pd.DataFrame(pd.read_excel(excel_file)) # 设置数据显示的列数和宽度 pd.set_option('display.max_columns', 500) pd.set_option('display.width', 1000) # 解决数据输出时列名不对齐的问题 pd.set_option('display.unicode.ambiguous_as_wide', True) pd.set_option('display.unicode.east_asian_width', True) # 按“销量”列降序排序 df = df.sort_values(by='销量', ascending=False) # 最大值排名(对销量相同的产品,按照顺序排名并取最大值作为排名) df['最大值排名'] = df['销量'].rank(method='max', ascending=False) print(df[['图书名称', '销量', '最大值排名']].head(10))
原创文章,转载请注明出处:http://www.opcoder.cn/article/37/