Python3数据分析——Pandas库入门(数据结构篇)
前言
本文是博主参照Pandas文档做的Pandas库学习笔记,根据个人水平对内容作了增删
翻译可能并不准确,说明可能不够完整或准确
如有补充或发现错误,请读者不吝赐教!
文章目录
Pandas库
以下内容为Pandas文档的说明,基于个人理解翻译,讲述了Pandas的基本功能和理念,有助于学习Pandas。
亮点
- 提供了快速高效的
DataFrame
对象用于可集成索引的数据操作; - 可以读取或写入多种格式的表格类似的数据,如SQL或Excel;
- 自动显式地进行数据对齐和缺失数据的集成处理,将凌乱的数据整理得有序;
- 灵活的数据集重塑和旋转;
- 基于标签的智能切片、花式索引和大型数据集的子集化;
DataFrame
对象的大小可变,支持移除或插入;- 按引擎使用功能强大的组聚合或转换数据 允许对数据集进行拆分-应用-组合操作;
- 数据集的高性能合并和连接;
- 分层轴索引提供了一种在低维数据结构中处理高维数据的直观方法;
- 时间序列功能:日期范围生成和频率转换,移动窗口统计,日期移动和滞后。 甚至可以创建特定于域的时间偏移量和加入时间系列而不会造成数据丢失;
- 针对性能进行了高度优化,关键代码路径以 Cython 或 C 编写。
- 带有
Pandas
的Python程序可以用于各种学术和商业领域,包括金融、神经科学、经济学、 统计、广告、网络分析等。
期望
数据分析和操作的软件应该具有的特征:
- 面向所有人
- 可以免费使用和修改
- 灵活
- 强壮
- 方便使用
- 快速
使用Pandas的环境
推荐使用anaconda
构建的科学数据分析环境,里面携带有完整的Pandas库以及其他180+种库,可以有效避免附属库不全带来的学习问题。
Pandas库的两种重要数据结构
Pandas库中有两个重要的对象,Series
和DataFrame
,这两个对象也是Pandas中的两个重要的数据结构。
Series
对象
Series
类似于一维数组,由一组数据和一个标签组成,亦可没有标签。
创建Series
对象
创建Series
对象的标准语句:
s = pandas.Series(data=None, index=None, dtype=None, name=None, copy=False, fastpath=False)
data
:表示数据,支持列表、字典、numpy数组、标量值。index
:行标签,必须与数据长度相同,允许重复,但必须是可哈希类型。dtype
:指定输出类型,可以是str
、numpy.dtype
或ExtensionDtype
,若没有指定则自动判断。name
:为这个Series取名,输入为字符串。copy
:输入为布尔值,用于复制输入的数据,而不是链接到数据(指向同一个对象还是赋值一个新对象),默认为False
(指向同一个对象)。仅当Series
对象或一维ndarray
(Numpy的数组对象)作为时输入有效。- 返回值:
Series
对象
data
值的特殊情况下index
的取值
data
值是多维数组的情况:index
的长度应该是len(data)
,即data
的长度。data
值是字典的情况:如果index
没有传入值(为None
),则将data
的键将作为索引;若index
有传入,则根据index
索引data
内对应的键值对来创建Series
对象,如果index
存在无法对应的键值对,则保留键但是值为NaN
。
>>> s = pd.Series(data={'a':1, 'b':2, 'c':3}, index=['a', 'b', 'x'])
>>> s
a 1.0
b 2.0
x NaN
dtype: float64
data
输入为字典,但是index
同样有输入,此时将index
的值作为键索引data
,得到a
和b
的键值对,但是没有得到x
的键值对,故将x
的值设为NaN
然后存入a
和b
对应的键值对。
Series
对象的位置索引
假设有一个Series
对象:
>>> s = pd.Series(data={'标签1':1, '标签2':2, '标签3':3, '标签4':4})
>>> s
标签1 1
标签2 2
标签3 3
标签4 4
dtype: int64
- 默认索引:采用形如Python列表的方式,用
[0]
索引第一个数,[1]
索引第二个数,以此类推,但是不能用[-1]
索引。 - 标签索引单个数:在有标签的情况下,可以通过索引标签得到数,同样用
[标签]
实现。 - 标签索引多个数:在有标签的情况下,可以用
[['标签1', '标签2']]
同时索引多个标签,可以理解为在[]
内包含一个列表。 - 通过标签切片索引:在有标签的情况下,可以用
['标签1':'标签3']
索引一个标签切片,返回从标签1
到标签3
的三个数据,包头包尾。 - 通过位置切片索引:用
[0:3]
索引切片,得到标签1
到标签2
的数据,包头不包尾。
查看Series
的索引或值
对Series
对象调用index
属性可以获得索引,调用values
可以获得值。
>>> s.index
Index(['标签1', '标签2', '标签3', '标签4'], dtype='object')
>>> s.values
array([1, 2, 3, 4], dtype=int64)
返回值都为元组,第一个值为列表,包含所有的索引或值,第二个值可能存在,指示储存对象的类型。
DataFrame对象
DataFrame
对象是一个大小可变的二维表格数据。
创建DataFrame对象
创建DataFrame
对象的标准语句:
d = pandas.DataFrame(data=None, index=None, columns=None, dtype=None, copy=None)
data
:数据内容,可以是ndarray(结构化或同构)对象、可迭代对象、字典或列表。index
:行索引,若输入数据和index
均未提供索引,则提供默认索引。columus
:列索引,同样在没有输入时提供从0开始的默认索引。dtype
:强制数据类型,只允许单个数据类型,若没有提供则会自动判断。copy
:复制,布朗值,默认为False
,即不复制,采用链接的方法。仅对包含多个Series
对象的字典生效。
data
值的特殊情况
data
值输入为字典时,字典可以包含数组等类似列表的对象,如果字典内是列表等数据,DataFrame
中列的顺序是字典中键值对的顺序 ;如果字典内的数据是Series
对象,则会根据Series
对象的索引匹配数据的顺序。同时字典中含有多个列表,则要求列表的长度相同,否则只能填入单个数据,这个数据会被填充至与列表长度相同。
>>> df = pd.DataFrame(data={'游戏1':[550, 554, 493], '游戏2':[453, 546, 602], '游戏3':[321, 301, 310], '游戏4':0}, index=['1月', '2月', '3月'])
>>> df
游戏1 游戏2 游戏3 游戏4
1月 550 453 321 0
2月 554 546 301 0
3月 493 602 310 0
DataFrame
常用方法
方法 | 描述 |
---|---|
DataFrame.describe() | 生成描述性统计信息 |
DataFrame.abs() | 返回一个包含所有元素的绝对值的DataFrame |
DataFrame.copy([deep]) | 复制此对象的索引和数据 |
DataFrame.count([axis, level, numeric_only]) | 计算每行或每列的非空个数 |
DataFrame.compare(other[, align_axis, keep_shape, ...]) | 比较两个DataFrame 并打印不同之处 |
DataFrame.idxmax([axis, skipna, numeric_only]) | 返回某一列的最大值首次出现的index (索引) |
DataFrame.idxmin([axis, skipna, numeric_only]) | 返回某一列的最小值首次出现的index (索引) |
DataFrame.max([axis, skipna, level, numeric_only]) | 返回每一列(或指定列)的最大值 |
DataFrame.min([axis, skipna, level, numeric_only]) | 返回每一列(或指定列)的最小值 |
DataFrame.sum([axis, skipna, level, numeric_only, ...]) | 返回每一列(或指定列)忽略空值后的和 |
DataFrame.mean([axis, skipna, level, numeric_only]) | 返回每一列(或指定列)的平均值 |
DataFrame.median([axis, skipna, level, numeric_only]) | 返回每一列(或指定列)的中位数 |
DataFrame.var([axis, skipna, level, ddof, numeric_only]) | 返回每一列(或指定列)的方差 |
DataFrame.std([axis, skipna, level, ddof, numeric_only]) | 返回每一列(或指定列)的标准差 |
导入文件
导入.xls
或.xlsx
文件
方法:pandas.read_excel()
返回值:DataFrame
对象
完整语句:
pandas.read_excel(io, sheet_name=0, *, header=0, names=None, index_col=None, usecols=None, squeeze=None, dtype=None, engine=None, converters=None, true_values=None, false_values=None, skiprows=None, nrows=None, na_values=None, keep_default_na=True, na_filter=True, verbose=False, parse_dates=False, date_parser=None, thousands=None, decimal='.', comment=None, skipfooter=0, convert_float=None, mangle_dupe_cols=True, storage_options=None)
常用参数解释:
io
:需要读取的对象,支持str, bytes, ExcelFile, xlrd.Book, path object, or file-like object
输入,既可以是文件位置也可以是文件流。sheet_name
:需要读取的单元表,支持str, int, list, or None
,默认为0(第一个单元表)。若为字符串,则为单元表名称;若为int型,则为单元表的位置(从0开始为第一个);若为列表,则为列表所指的所有单元表;若为None
,则加载全部单元表。header
:用作列名的行,支持int
数据和由int
组成的列表,默认为0(第一行作列名,第一行以外作为数据传入)。names
:额外的列名,传入此参数时会强制header=0
,如果文件第一行不是列名,则需要特地将header=None
传入,避免丢失第一行数据。支持类似数组的传入。index_col
:指定文件中作为行名的列,类似header
但这里是行名。支持int
和int
构成的数组(关于多索引和空值问题不做描述)。usecols
:需要解析的列,支持字符串,列表,可调用(callable
)对象。如果为None
,则解析所有列;如果为字符串,则可以用,
多选,用:
表范围选择(字母索引);数字列表则表示位置位置索引(从0开始);字符串列表表述要解析的列名列表(字母);若为可调用对象,可调用对象会被传入列名,根据可调用对象的返回值,若为True
则调用该列。squeeze
:如果传入数据只有一列,则返回一个Series
对象而非DataFrame
对象。默认值为False
,即仍然返回DataFrame
对象。dtype
:指定列的类型,支持字典,默认为None
,例如 {‘a’: np.float64, ‘b’: np.int32}。skiprows
:需要跳过的行号(0索引),或从头计要忽略的行数(int)。支持int
类型和列表,可调用对象。skipfooter
:从尾计要忽略的行数(int)。支持int
类型,默认为0。
导入.csv
文件
方法:pandas.read_csv()
返回值:DataFrame
对象
完整语句:
pandas.read_csv(filepath_or_buffer, *, sep=_NoDefault.no_default, delimiter=None, header='infer', names=_NoDefault.no_default, index_col=None, usecols=None, squeeze=None, prefix=_NoDefault.no_default, mangle_dupe_cols=True, dtype=None, engine=None, converters=None, true_values=None, false_values=None, skipinitialspace=False, skiprows=None, skipfooter=0, nrows=None, na_values=None, keep_default_na=True, na_filter=True, verbose=False, skip_blank_lines=True, parse_dates=None, infer_datetime_format=False, keep_date_col=False, date_parser=None, dayfirst=False, cache_dates=True, iterator=False, chunksize=None, compression='infer', thousands=None, decimal='.', lineterminator=None, quotechar='"', quoting=0, doublequote=True, escapechar=None, comment=None, encoding=None, encoding_errors='strict', dialect=None, error_bad_lines=None, warn_bad_lines=None, on_bad_lines=None, delim_whitespace=False, low_memory=True, memory_map=False, float_precision=None, storage_options=None)
常用参数解释:
filepath_or_buffer
:文件位置或文件流,支持字符串,路径对象和类文件对象,支持URL链接。sep
:分隔符,支持字符串,默认为,
。delimiter
:与sep
相同,支持字符串,默认为None
。header
:用作列名的行,支持int
数据和由int
组成的列表,默认为infer
(系统会根据第一行推断,假设推断为第一行作列名,则第一行以外作为数据传入)。此外,若显示传递列名,则表现为直接采用显式传递的列名,此时为header=None
,即第一行会作为数据传入,避免第一行作为多余数据出现,需要额外设定header=0
。name
:额外的列名,如果数据第一行同样是列名,则需要特地将header=0
传入。支持类似数组的传入。index_col
:指定文件中作为行名的列。支持int
,字符串和int
或字符串构成的数组(关于多索引和空值问题不做描述)。index_col=False
可以强制Pandas
不适用第一列作为索引,可用于解决格式错误导致的问题。usecols
:需要解析的列,支持字符串,列表,可调用(callable
)对象。如果为None
,则解析所有列;如果为字符串,则可以用,
多选,用:
表范围选择(字母索引);数字列表则表示位置位置索引(从0开始);字符串列表表述要解析的列名列表(字母);若为可调用对象,可调用对象会被传入列名,根据可调用对象的返回值,若为True
则调用该列。dtype
:指定列的类型,支持字典,默认为None
,例如 {‘a’: np.float64, ‘b’: np.int32}。parse_dates
:设置该参数可直接将某列转化为datetime64
的日期类型。支持布朗值,列表或字典,默认为False
。当传入True
时,解析索引(尝试索引是否能转化为datetime64
的日期类型?);传入int
类型值组成的列表时,将指定列解析为datetime64
的日期类型(1索引);传入列表组成的列表时,则将内部列表的信息合并解析为一个datetime64
的日期类型;传入字典时,键将作为列名,值可以是整型或列表。encoding
:指定文件编码格式。支持字符串,默认为None
。
导入.txt
文件
方法:pandas.read_csv()
返回值:DataFrame
对象
具体语句见上文。
导入HTML网页的表格
方法:pandas.read_html()
该方法用于导入带有table
标签的网页,同时需要安装lxml
模块保障其基本运行。
返回值:DataFrame
对象
完整语句:
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, extract_links=None)
常用参数解释:
io
:网站路径,可以是字符串,路径对象,文件对象。match
:正则表达式,用于匹配网站table
节点,除非网站非常简单,否则需要传递一个非空字符串。默认为.+
(所有非空字符串,将返回页面上包含的所有表)。flavor
: 解析器(-调味-),指定分析所用的引擎,默认为None
,使用lxml
解析,若失败则采用bs4+HTML5lib
解析。header
:指定列标题所在的行。支持整型和列表(多重索引)。index_col
:指定行标题所在的列。支持整型和列表。encoding
:内容编码格式,默认为None
,应输入字符串。skiprows
:需要跳过的行号(0索引),或从头计要忽略的行数(int)。支持int
类型和列表(单个元素的列表表示跳过第n行,整数表示跳过n行,允许切片),可调用对象。
数据抽取
DataFrame.loc[]属性
DataFrame.loc[]
属性解析索引的标签(名称),而不是索引的位置(序号),返回值根据返回内容可能是DataFrame
或Series
数据类型。方括号内第一个元素为行标签,第二个元素为列标签,即[行, 列]
。
方括号的元素可以为如下几种:
- 单个数据:如
5
或'a'
,将索引行标签(名称),其中5
也代表名称而不是位置。 - 标签列表或元组:如
['a', 'b', 'c']
,支持切片,需要注意的是包头包尾。 - 与已经被切片后的数组长度相等的布尔数组:如
[True, False, True]
。 - 内容为布尔值且名称对应的
Series
对象。 - 可以对应的
Index
对象,将返回对应Index
的数据。
DataFrame.iloc[]属性
DataFrame.iloc[]
属性与DataFrame.loc[]
属性,根据位置(序号,0索引)寻找数据,同样方括号内第一个元素为行标签,第二个元素为列标签,即[行, 列]
。
方括号内的元素可以是:
- 单个数据,如
5
索引第六个位置。 - 整型列表或元组,如
[2, 3, 4]
。 - 整型切片对象,如
1:7
,需要注意的是包头不包尾。 - 与索引长度相同的布尔数组。
对于切片,可以使用[:, 'a':]
等索引,,
左侧为全选,右侧为从a
开始往后选择所有索引。同样,:2
表示0,1
(在iloc
内)可以从头开始到2
结束。
条件选择
例子摘自Pandas文档:
# 原数据展示
>>> df = pd.DataFrame([[1, 2], [4, 5], [7, 8]],
... index=['cobra', 'viper', 'sidewinder'],
... columns=['max_speed', 'shield'])
>>> df
max_speed shield
cobra 1 2
viper 4 5
sidewinder 7 8
# 抽取'shield'大于6的对象的'max_speed'
>>> df.loc[df['shield'] > 6, ['max_speed']]
max_speed
sidewinder 7
实现方法:
df['shield'] > 6
:df['shield']
返回shield
列的Series
对象后,筛选其中>6
的行,作为第一个元素传入loc[]
属性。
数据的修改
通过属性修改
- 修改列名:
DataFrame.columns=[]
,但是列表长度必须与原来的列数相等(不能像列表一样直接df.columns[1] = 'C'
,错误类型为TypeError: Index does not support mutable operations
)。 - 修改行名:
DataFrame.index=[]
,同样需要列表长度与原来行数相等。 - 修改数据:
DataFrame.loc[]=[]
,或DataFrame.iloc[]=[]
,即抽取数据后直接赋值即可改变数据。
DataFrame.rename()
方法修改索引
完整语句:
DataFrame.rename(mapper=None, *, index=None, columns=None, axis=None, copy=None, inplace=False, level=None, errors='ignore')
- 修改列名:
DataFrame.rename(columns=*)
,*
为传入值,应为字典,且键为原先的列名,值为修改后的列名。- 该方法等效于
DataFrame.rename(mapper=*, axis='columns')
(*
为字典,同上)。
- 该方法等效于
- 修改行名:
DataFrame.rename(index=*)
,*
为传入值,应为字典,且键为原先的行名,值为修改后的行名。- 该方法等效于
DataFrame.rename(mapper=*, axis='index')
(*
为字典,同上)。
- 该方法等效于
重要参数解释:
inplace
:是否修改原先的DataFrame
而不是创建一个新的,布尔值,默认为False
(创建新的DataFrame
作为返回值,保留原先的DataFrame
)。axis
:轴所在位置,可取0、1,或'index'
、'columns'
0表示修改行名称,1表示修改列名称,默认为0修改行名称。level
:层,适用于多层index
重命名,支持整型和层名,默认为None
。errors
:错误提示,如果字典内出现不存在的原名,是否提示KeyError
。参数值应为ignore
(默认值,忽略无法与任何原名对应的键,并且不报错)或raise
(如有键对应的原名不存在,则发生KeyError
错误)。
增加数据
增加一列数据
- 直接赋值:
DataFrame['列名'] = [数据]
loc
属性赋值:DataFrame.loc[:, '列名'] = [数据]
insert()
方法:
用DataFrame.insert()
方法在DataFrame
的指定位置增加一列。
完整语句:
DataFrame.insert(loc, column, value, allow_duplicates=_NoDefault.no_default)
参数描述:
loc
:指定插入位置,支持整型,只能取大于等于0
且小于等于len(columns)
的数。column
:指定列名,插入列的标签。支持字符串,数字。value
:指定需要插入的数据,支持Series
对象,列表等。
注意:
iloc
属性不能增加对象的值,报错信息:IndexError: iloc cannot enlarge its target object
增加一行数据
loc
属性赋值:DataFrame.loc['行名'] = [数据]
- 补充一个列名相同的
DataFrame
对象
DataFrame.drop()
方法删除数据
方法描述:删除指定行或列的数据。
完整语句:
DataFrame.drop(labels=None, *, axis=0, index=None, columns=None, level=None, inplace=False, errors='raise')
参数描述:
labels
:目标行标签或列标签,支持单个或列表输入。axis
:指定行或列,行为0
或'index'
,列为1
或'columns'
,默认为0
。index
:单个行名或列表,使用index=labels
等价于labels, axis=0
。columns
:单个列名或列表,使用columns=labels
等价于labels, axis=1
。level
:多层index
时使用,指定要删除的index
所在的级别,0索引。inplace
:是否修改原先的DataFrame
而不是创建一个新的,布尔值,默认为False
(创建新的DataFrame
作为返回值,保留原先的DataFrame
)。errors
:错误提示,如果需要删除的参数中出现不存在的标签,是否提示KeyError
。参数值应为ignore
或raise
,默认为raise
(提示错误)。
数据清洗
数据缺失
数据缺失的处理办法:
不处理
删除
填充或替换
插入特殊值(中位数,均值,众数等)
如果缺失数据比例大于30%,则可以选择放弃指标,删除。
如果缺失数据比例小于30%,则尽量对数据进行填充。
查找缺失值
- 使用
info()
方法查看DataFrame
的统计数据 - 使用
isnull()
或notnull()
方法查看DataFrame
缺失值所在位置
删除缺失数据
方法:DataFrame.dropna()
描述:移除丢失数据,无参数可以直接使用,将删除所有存在缺失值的行。
完整语句:
DataFrame.dropna(*, axis=0, how=_NoDefault.no_default, thresh=_NoDefault.no_default, subset=None, inplace=False)
参数解释:
axis
:指定删除的轴,行为0
或'index'
,列为1
或'columns'
,默认为0
,删除存在缺失值的行。how
:指定是整行为空才删除(all
),还是存在空值才删除(any
),默认为any
,即存在空值才删除。thresh
:指定存在多少非空值,不能与how
同时存在,输入为整型。subset
:指定检索的标签,仅当这个参数传入的标签或标签列表所对应的数据存在空值时,才删除数据。比如,指定删除行,并且为这个参数传入一个列表,那么将检索这个列表内对应的列标签,若这些列标签中存在空值,则删除空值所在的行。inplace
:是否修改原先的DataFrame
而不是创建一个新的,布尔值,默认为False
(创建新的DataFrame
作为返回值,保留原先的DataFrame
)。
填充缺失数据
方法:DataFrame.fillna
描述:用特殊方法填充空数据(NA
/NaN
)
完整语句:
DataFrame.fillna(value=None, *, method=None, axis=None, inplace=False, limit=None, downcast=None)
参数解释:
value
:希望填充的值,如0。若参数值为字典,series
对象,DataFrame
对象,则根据对应的标签对应填充,不存在的标签不填充。不支持列表。method
:用特殊方法填充,参数为{‘backfill’, ‘bfill’, ‘pad’, ‘ffill’, None}
,默认为None
pad/ffill
作为参数的时候,用该空缺位的前一个非空值填充。backfill/bfill
作为参数的时候,用该空缺位的后一个非空值填充。None
作为参数的时候,将使用value
填充。
axis
:指定沿着什么轴检索,行为0
或'index'
,列为1
或'columns'
,默认为0
。inplace
:是否修改原先的DataFrame
而不是创建一个新的,布尔值,默认为False
(创建新的DataFrame
作为返回值,保留原先的DataFrame
)。limit
:限制method
参数沿着axis
轴对连续非空值填充的最大限度,到达限度后将不再为后面连续的空值填充,支持整型和None
,若位整型则必须大于0。downcast
:如果有需要,将改变从非空值取得的填充值的数据类型。支持字典输入,默认None
。
数据重复
查看重复数据
方法:DataFrame.duplicated()
描述:检索重复行,并返回表示重复行的布尔Series
对象(这个对象内True
表示重复的行)。
完整语句:
DataFrame.duplicated(subset=None, keep='first')
参数解释:
subset
:需要考虑的列名,或列名列表。寻找重复行时则只会考虑这些列。默认所有列。keep
:需要标记为True
的重复项的排除项,参数可以是first
,last
,False
,其中first
表示除了第一个重复行其余重复行都标记为True
;last
表示除了最后一个重复行都其余重复行都标记为True
;False
表示所有重复行均标记为True
。
删除重复数据
方法:DataFrame.drop_duplicated()
描述:检索重复行,并返回删除重复行后的DataFrame
对象。
完整语句:
DataFrame.drop_duplicates(subset=None, *, keep='first', inplace=False, ignore_index=False)
参数解释:
subset
:需要考虑的列名,或列名列表。寻找重复行时则只会考虑这些列。默认所有列。keep
:需要保留的重复项的排除项,参数可以是first
,last
,False
,其中first
表示除了第一个重复行其余重复行都删除;last
表示除了最后一个重复行都其余重复行都删除;False
表示所有重复行均删除。inplace
:是否修改原先的DataFrame
而不是创建一个新的,布尔值,默认为False
(创建新的DataFrame
作为返回值,保留原先的DataFrame
)。ignore _index
:是否重新编号,如果重新编号(True
)则返回值的行将从0开始重新编号。默认为False
。
附录:Pandas类型与Python类型对照表
Pandas 数据类型 | Python 数据类型 |
---|---|
object | str |
int64 | int |
float64 | float |
bool | bool |
datetime64 | datetime64[ns] |
timedelta[ns] | NA |
category |