05_Pandas数据结构
文章目录
- 1 Series对象
- 1.1 创建 Series 对象
- 1.2 Series 的运算
- 1.2.1 标量运算
- 1.2.2 矢量运算
- 1.3 Series 的属性
- 1.4 Series 的方法
- 1.4.1 描述性统计
- 1.4.2 处理数据
- 1.4.3 排序
- 1.4.4 绘制图表
- 2 DataFrame 对象
- 2.1 创建 DataFrame 对象
- 2.1.1 通过二维数组/列表创建
- 2.1.2 通过字典创建
- 2.2 数据读取和存储
- 2.2.1 读取 Excel
- 2.2.2 读取 CSV
- 2.2.3 读取其他文件
- 2.2.4 存储数据
- 2.3 DataFrame 的属性
- 2.4 DataFrame 的方法
- 3 Index 对象
- 3.1 Index 的特点
- 3.2 Index 常用操作
Numpy和Pandas的关系:就像先掌握算术才能学代数一样,NumPy就是数据分析的"算术基础",虽然可以直接用计算器(Pandas),但理解底层原理才能走得更远。
Pandas 核心数据机构是Series
(数据系列)、DataFrame
(数据窗/数据框),Series
可以看做表中的一列,DataFrame
则是整个表格,由多个列构成。除此之外还有一个特殊的Index
类,为Series
和DataFrame
提供索引功能。
1 Series对象
1.1 创建 Series 对象
Series
对象内部结构:一个ndarray用来保存数据,一个index用来保存索引。类似Numpy的一维数组,但是增加了“标签”,具有数据和索引。
- 通过列表和数组创建
data
:数据index
:索引name
:名称
其中name
的作用:
- 创建
DataFrame
时自动变成列名 - 合并时作为对齐依据
- 导出csv时成为列名
import numpy as np
import pandas as pdser1 = pd.Series(data=np.arange(4), index=['春', '夏', '秋', '冬'], name='季节')
ser1
春 0
夏 1
秋 2
冬 3
Name: 季节, dtype: int32
- 通过字典创建
- 字典的键就是索引
- 字典的值就是数据
ser2 = pd.Series(data={'春': 1, '夏': 2, '秋': 3, '冬': 4})
ser2
春 1
夏 2
秋 3
冬 4
dtype: int64
1.2 Series 的运算
由于 Pandas 是基于 Numpy 开发的,所以很多性质和数组是一样的,比如矢量化运算和广播。
1.2.1 标量运算
ser1 += 10
ser1
春 10
夏 11
秋 12
冬 13
dtype: int32
1.2.2 矢量运算
ser1 += ser2
ser1
春 11
夏 13
秋 15
冬 17
dtype: int64
1.3 Series 的属性
dtype
:返回Series
对象的数据类型
ser1.dtype
dtype('int64')
size
:返回Series
对象中元素的个数
ser1.size
4
index
:返回Series
对象的索引Index
对象
print('索引对象', ser1.index)
print('通过下标取出具体索引', ser1.index[0])
索引对象 Index(['春', '夏', '秋', '冬'], dtype='object')
通过下标取出具体索引 春
values
:以ndarray
的形式返回Series
对象的值
print(ser1.values)
print('通过下标取出具体值', ser1.values[0])
[11 13 15 17]
通过下标取出具体值 11
1.4 Series 的方法
1.4.1 描述性统计
print('计数:', ser1.count())
print('求和:', ser1.sum())
print('均值:', ser1.mean())
print('中位数:', ser1.median())
print('最小值:', ser1.min())
print('最大值:', ser1.max())
print('标准差:', ser1.std())
print('方差:', ser1.var())
计数: 4
求和: 56
均值: 14.0
中位数: 14.0
最小值: 11
最大值: 17
标准差: 2.581988897471611
方差: 6.666666666666667
describe()
:获取描述性统计信息。
ser1.describe()
count 4.000000
mean 14.000000
std 2.581989
min 11.000000
25% 12.500000
50% 14.000000
75% 15.500000
max 17.000000
dtype: float64
describe()
返回的是一个Series
对象,所以可以通过索引访问。
print('平均值:', ser1.describe()['mean'])
print(f"最大值,最小值:\n{ser1.describe()[['max', 'min']]}")
平均值: 14.0
最大值,最小值:
max 17.0
min 11.0
dtype: float64
1.4.2 处理数据
isnull()
:空值判断notnull()
:非空值判断
ser2 = pd.Series(data=[10, 20, np.nan, 30, np.nan])
ser2.isnull()
0 False
1 False
2 True
3 False
4 True
dtype: bool
dropna()
:删除空值fillna()
:填充空值
处理数据的方法都有一个inplace
参数,默认为False
。
inplace=False
:处理完成返回新的对象inplace=True
:在原对象上进行处理
ser2.dropna()
0 10.0
1 20.0
3 30.0
dtype: float64
ser2.fillna(66, inplace=True)
ser2
0 10.0
1 20.0
2 66.0
3 30.0
4 66.0
dtype: float64
duplicated()
:检测重复数据drop_duplicates()
:删除重复数据unique
:去除重复数据,返回一个数组
ser2.duplicated()
0 False
1 False
2 False
3 False
4 True
dtype: bool
ser2.drop_duplicates()
0 10.0
1 20.0
2 66.0
3 30.0
dtype: float64
ser2.unique()
array([10., 20., 66., 30.])
1.4.3 排序
sort_index()
:根据索引排序,默认升序sort_values()
:根据值排序,默认升序
使用ascending=False
参数可以实现降序排列,排序结果返回一个新的 Series
对象,原对象不变。
ser3 = pd.Series(data=[30, 10, 20, 10, 50], index=['Bob', 'Alice', 'John', 'Eve', 'Jack'])
ser3.sort_index()
Alice 10
Bob 30
Eve 10
Jack 50
John 20
dtype: int64
ser3.sort_values(ascending=False, inplace=True)
ser3
Jack 50
Bob 30
John 20
Alice 10
Eve 10
dtype: int64
head(n)
:返回前 n 个元素,默认 n=5tail(n)
:返回后 n 个元素,默认 n=5
ser3.head(3)
Jack 50
Bob 30
John 20
dtype: int64
ser3.tail(2)
Alice 10
Eve 10
dtype: int64
1.4.4 绘制图表
Series
对象可以直接绘制图表,默认绘制折线图,还可以绘制柱状图、饼图等,只需指定kind
参数即可。默认会使用索引作为横坐标,值作为纵坐标。
import matplotlib.pyplot as plt
ser3.plot(kind='bar')
<Axes: >
2 DataFrame 对象
DataFrame
是一个二维的表格型数据结构,既有行索引,也有列索引,可以将其看作由多个Series
按列组成的一个字典。是 Pandas 中最常用的数据结构,可以用来保存和处理异质的二维数据,每个列可以是不同的数据类型,这也是和 NumPy 数组的最大区别。
数据表格三要素贯穿 Pandas 数据分析的始终:
column
:对应着列名,也就是列索引index
:代表行索引value
:则指代具体的数据值
2.1 创建 DataFrame 对象
2.1.1 通过二维数组/列表创建
data
指定数据,columns
指定列名,index
指定行索引。
如果没有指定索引,则默认从 0 开始。如果没有指定列名,则默认从 0 开始。
score = np.random.randint(0, 101, size=(5, 3))
course = ['语文', '数学', '英语']
stu_id = ['1001', '1002', '1003', '1004', '1005']
df1 = pd.DataFrame(data=score, columns=course, index=stu_id)
df1
语文 | 数学 | 英语 | |
---|---|---|---|
1001 | 1 | 83 | 92 |
1002 | 89 | 69 | 26 |
1003 | 90 | 12 | 74 |
1004 | 83 | 86 | 47 |
1005 | 73 | 93 | 71 |
2.1.2 通过字典创建
字典嵌套列表:按照列名进行创建 DataFrame
对象。
info1 = {'姓名': ['张三', '李四', '王五', '赵六'],'年龄': [18, 19, 20, 21],'性别': ['男', '女', '男', '女']
}
df2 = pd.DataFrame(data=info1)
df2
姓名 | 年龄 | 性别 | |
---|---|---|---|
0 | 张三 | 18 | 男 |
1 | 李四 | 19 | 女 |
2 | 王五 | 20 | 男 |
3 | 赵六 | 21 | 女 |
列表嵌套列表:按照行进行创建 DataFrame
对象。
info2 = [{'姓名': '张三', '年龄': 18, '性别': '男'},{'姓名': '李四', '年龄': 19, '性别': '女'},{'姓名': '王五', '年龄': 20, '性别': '男'},{'姓名': '赵六', '年龄': 21, '性别': '女'}
]
df3 = pd.DataFrame(data=info2)
df3
姓名 | 年龄 | 性别 | |
---|---|---|---|
0 | 张三 | 18 | 男 |
1 | 李四 | 19 | 女 |
2 | 王五 | 20 | 男 |
3 | 赵六 | 21 | 女 |
2.2 数据读取和存储
实际应用中,单独创建数据结构的情况较少,更多的是通过读取外部数据文件来创建数据结构。
2.2.1 读取 Excel
通过read_excel
读取 Excel 文件,默认读取第一个 sheet,可以通过sheet_name
参数指定读取的 sheet。
data1 = pd.read_excel('data/data1.xlsx')
data1
张三 | 88 | 100 | 90 | |
---|---|---|---|---|
0 | 李四 | 82 | 65 | 52 |
1 | 王五 | 80 | 92 | 60 |
Pandas 默认会将第一行数据作为列名,如果想自定义列名,可以将header=None
告诉Pandas数据中没有表头,然后通过names
参数指定列名。
data1 = pd.read_excel('data/data1.xlsx', header=None, names=['姓名', '语文', '数学', '英语'])
data1
姓名 | 语文 | 数学 | 英语 | |
---|---|---|---|---|
0 | 张三 | 88 | 100 | 90 |
1 | 李四 | 82 | 65 | 52 |
2 | 王五 | 80 | 92 | 60 |
此外读取数据还有很多参数,比如:
index_col
:指定哪一列作为行索引usecols
:指定读取哪些列nrows
:指定读取多少行dtype
:指定列的数据类型
2.2.2 读取 CSV
通过read_csv
函数可以读取 CSV 文件,默认使用UTF-8编码格式,如果是其他编码格式,可以通过encoding
参数指定。
data2 = pd.read_csv('data/data2.csv')
data2
姓名 | 语文 | 数学 | 英语 | |
---|---|---|---|---|
0 | 张三 | 88 | 100 | 90 |
1 | 李四 | 82 | 65 | 52 |
2 | 王五 | 80 | 92 | 60 |
大多数CSV文件以逗号分隔,如果是其他字符分
隔,可以通过sep
参数指定分隔符。
pd.read_csv('data/data2.csv', sep='\t')
在某些Python版本读取中文路径会报错,因为默认读取引擎是C语言,可以通过engine
参数指定为Python引擎。
pd.read_csv('data/data2.csv'mengine='python')
2.2.3 读取其他文件
Excel和CSV是最常用的,其他文件读取简单了解,读取文件的大部分参数是通用的。
read_table()
: 读取文本文件read_json()
: 读取 JSON 文件
2.2.4 存储数据
在Pandas中存储数据直接使用to_xxx()
方法即可,默认会把索引也存储进去,如果不需要索引,可以通过index=False
参数去掉索引。
data2.to_excel('data/new_data2.xlsx', index=False)
2.3 DataFrame 的属性
columns
:列索引index
:行索引values
:数据值
print(data2)print('\n列索引:', data2.columns)
print('行索引:', data2.index)
print('数据值:\n', data2.values)
姓名 语文 数学 英语
0 张三 88 100 90
1 李四 82 65 52
2 王五 80 92 60列索引: Index(['姓名', '语文', '数学', '英语'], dtype='object')
行索引: RangeIndex(start=0, stop=3, step=1)
数据值:[['张三' 88 100 90]['李四' 82 65 52]['王五' 80 92 60]]
dtypes
:每一列的数据类型
data2.dtypes
姓名 object
语文 int64
数学 int64
英语 int64
dtype: object
ndim
:维度shape
:形状size
:元素个数
print('维度', data2.ndim)
print('形状', data2.shape)
print('元素个数', data2.size)
维度 2
形状 (3, 4)
元素个数 12
2.4 DataFrame 的方法
info()
:查看DataFrame的基本信息
data2.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3 entries, 0 to 2
Data columns (total 4 columns):# Column Non-Null Count Dtype
--- ------ -------------- ----- 0 姓名 3 non-null object1 语文 3 non-null int64 2 数学 3 non-null int64 3 英语 3 non-null int64
dtypes: int64(3), object(1)
memory usage: 224.0+ bytes
describe()
:获取统计性描述信息
DataFrame也有很多统计性描述信息的方法,和Series一致,此处不再赘述。不过多了一个axis
参数控制聚合轴向:
axis=0
:按列进行统计axis=1
:按行进行统计
data2.describe()
语文 | 数学 | 英语 | |
---|---|---|---|
count | 3.000000 | 3.000000 | 3.000000 |
mean | 83.333333 | 85.666667 | 67.333333 |
std | 4.163332 | 18.339393 | 20.033306 |
min | 80.000000 | 65.000000 | 52.000000 |
25% | 81.000000 | 78.500000 | 56.000000 |
50% | 82.000000 | 92.000000 | 60.000000 |
75% | 85.000000 | 96.000000 | 75.000000 |
max | 88.000000 | 100.000000 | 90.000000 |
cumsum()
:累计和cumprod()
:累计积cummax()
:累计最大值cummin()
:累计最小值
data2.cumsum()
姓名 | 语文 | 数学 | 英语 | |
---|---|---|---|---|
0 | 张三 | 88 | 100 | 90 |
1 | 张三李四 | 170 | 165 | 142 |
2 | 张三李四王五 | 250 | 257 | 202 |
data2.cummin()
姓名 | 语文 | 数学 | 英语 | |
---|---|---|---|---|
0 | 张三 | 88 | 100 | 90 |
1 | 张三 | 82 | 65 | 52 |
2 | 张三 | 80 | 65 | 52 |
head(n)
:查看前n行数据,默认n=5tail(n)
:查看后n行数据,默认n=5
data2.head(2)
姓名 | 语文 | 数学 | 英语 | |
---|---|---|---|---|
0 | 张三 | 88 | 100 | 90 |
1 | 李四 | 82 | 65 | 52 |
data2.tail(3)
姓名 | 语文 | 数学 | 英语 | |
---|---|---|---|---|
0 | 张三 | 88 | 100 | 90 |
1 | 李四 | 82 | 65 | 52 |
2 | 王五 | 80 | 92 | 60 |
sort_index()
:根据索引排序,默认升序sort_values()
:根据值排序,默认升序
使用ascending=False
参数可以实现降序排列。
data2.sort_index(ascending=False)
姓名 | 语文 | 数学 | 英语 | |
---|---|---|---|---|
2 | 王五 | 80 | 92 | 60 |
1 | 李四 | 82 | 65 | 52 |
0 | 张三 | 88 | 100 | 90 |
data2.sort_values('英语')
姓名 | 语文 | 数学 | 英语 | |
---|---|---|---|---|
1 | 李四 | 82 | 65 | 52 |
2 | 王五 | 80 | 92 | 60 |
0 | 张三 | 88 | 100 | 90 |
3 Index 对象
Index
用来唯一标识 DataFrame 中的每一行数据,就像数据库表中的主键一样,但它不强制要求是唯一的,类似于一维数组,存储着用于标记各行数据的标签。
3.1 Index 的特点
- 标签:作为行标签使用,用来访问特定行
df.loc[行标签]
- 对齐:两个
DataFrame
之间运算(比如加法、合并等)时,Pandas根据Index
和Column
自动将数据对齐,而不需要行和列的顺序相同 - 不可变性:
Index
对象一旦创建,不允许被修改,所有修改索引必须整体修改
3.2 Index 常用操作
data2
姓名 | 语文 | 数学 | 英语 | |
---|---|---|---|---|
0 | 张三 | 88 | 100 | 90 |
1 | 李四 | 82 | 65 | 52 |
2 | 王五 | 80 | 92 | 60 |
index
:查看index
data2.index
RangeIndex(start=0, stop=3, step=1)
set_index()
:将普通列设为行索引。
df.set_index(keys, drop=True, inplace=False)
- keys:新索引的列名或列名列表
- drop:用于创建新索引的列是否从表中删除,默认为True
- inplace:是否在原表修改
data3 = data2.set_index('姓名')
data3
语文 | 数学 | 英语 | |
---|---|---|---|
姓名 | |||
张三 | 88 | 100 | 90 |
李四 | 82 | 65 | 52 |
王五 | 80 | 92 | 60 |
reset_index
:set_index
的逆操作,将索引重置为普通列,并且创建一个新的RangeIndex
作为索引。
df.reset_index(drop=False, name=None, inplace=False)
- drop:是否删除原有索引,不转化为普通列,默认为False
- names:指定转为为普通列之后的名称
- inplace:是否在原表修改
data3.reset_index(names='大名')
大名 | 语文 | 数学 | 英语 | |
---|---|---|---|---|
0 | 张三 | 88 | 100 | 90 |
1 | 李四 | 82 | 65 | 52 |
2 | 王五 | 80 | 92 | 60 |