数据分析、数据挖掘、可视化是 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: intlist  字符串,默认值为 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 链接

sepdelimiter: 字符串,分隔符

header: 指定作为列名的行,默认值为0,即取第一行的值为列名。若数据不包含列名,则设置为 header=None

names: 默认值为 None,要使用的列名列表

index_col: 指定列为索引列,默认值为 None

usercols: intlist  字符串,默认值为 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],则解析123列的值作为独立的日期列
  - parse_dates为列表组成的列表时,如[[1,3]],则将13列合并,作为一个日期列使用
  - parse_dates为字典时,如{'总计':[1,3]},则将13列合并,合并后的列名为“总计”

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,重新设置索引时,选择插入值(用来填充缺失数据)方法,其值可以是Nonebfill/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))

sort_values01

  • 按多列数据排序
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)

sort_values02

  • 对分组统计结果排序
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))

sort_value03

  • 平均排名
# 平均排名(对销量相同的产品,按照顺序排名的平均值进行排名)
df['平均排名'] = df['销量'].rank(ascending=False)
print(df[['图书名称', '销量', '平均排名']].head(10))

sort_value04

  • 最小值排名
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))

sort_value05

  • 最大值排名
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))

sort_value06

原创文章,转载请注明出处:http://www.opcoder.cn/article/37/