目录
一、概述
Pandas是基于NumPy的一种工具,该工具是为解决数据分析任务而创建的,Pandas提供了大量能使我们快速便捷地处理数据的功能。
Pandas与出色的Jupyter工具包和其他库结合,Python中用于进行数据分析的环境在性能,生产率和协作能力方面都是卓越的。
Pandas的主要数据结构是Series(一维数据)与DantFrame(二维数据),这两种数据结构足以处理金融、统计、社会科学、工程等领域里的大多数案例。
处理数据一般分为几个阶段:数据整理与清洗、数据分析与建模、数据可视化、Pandas是处理数据的理想工具。
二、Pandas数据结构
Series
Series是一种类似于一维数组的对象,由下面两部分组成:
①、values:一组数组(ndarray类型)
②、index:相关的数据索引标签。
Series的创建
Pandas两种创建方式
1、由列表或NumpPy数组创建
默认索引为0到N - 1的整数型索引
import pandas as pd
li = [9, 8, 7, 6, 5]
# 由列表创建Series
a = pd.Series(li)
print(a)
import pandas as pd
import numpy as np
# 由numpy创建Series
lis = np.array(li)
a = pd.Series(lis)
print(a)
"""
输出结果:
0 9
1 8
2 7
3 6
4 5
dtype: int64
0 9
1 8
2 7
3 6
4 5
dtype: int64
"""
可以利用 index 属性,在创建的时候指定索引,还可以根据索引来获取值或修改值。
import pandas as pd
li = [9, 8, 7, 6, 5]
# 由列表创建Series
a = pd.Series(li, index=[list('ABCDE')])
print(a)
"""
输出结果:
A 9
B 8
C 7
D 6
E 5
dtype: int64
"""
利用索引来获取值。
①、当索引为数值时,只能使用 a[] 的形式来获取值
②、当索引是被指定的字符或字符串的时候可以通过 a.A 或者 a['A'] 的形式来获取索引所在的值
import pandas as pd
li = [9, 8, 7, 6, 5]
# 由列表创建Series
a = pd.Series(li, index=[list('ABCDE')])
print(a.A, a['A'])
"""
输出结果:
9 9
"""
利用索引来修改值
①、直接利用索引来修改值 a.A = 99 或 a['A'] = 99
import pandas as pd
li = [9, 8, 7, 6, 5]
# 由列表创建Series
a = pd.Series(li, index=[list('ABCDE')])
a['A'] = 99
print(a)
"""
输出结果:
A 99
B 8
C 7
D 6
E 5
dtype: int64
"""
利用values属性取出Pandas的值, 利用index属性取出Pandas的索引。
import pandas as pd
li = [9, 8, 7, 6, 5]
# 由列表创建Series
a = pd.Series(li, index=[list('ABCDE')])
print(a.values)
print(list(a.index), a.index, sep='\n')
"""
输出结果:
[9 8 7 6 5]
[('A',), ('B',), ('C',), ('D',), ('E',)]
MultiIndex([('A',),
('B',),
('C',),
('D',),
('E',)],
)
"""
2、由字典创建
import pandas as pd
a = {'a': [1, 2, 3],
'b': 2,
'c': 3,
'd': 4}
print(pd.Series(a))
"""
输出结果:
a [1, 2, 3]
b 2
c 3
d 4
dtype: object
"""
Series的索引
可以使用中括号取单个索引(此时返回的是元素类型), 或者中括号里一个列表取多个索引(此时返回的仍然是一个Series类型)。分别显示索引和隐士索引。
1、显示索引
①、使用 index 中的元素作为索引值
②、使用.loc[](推荐)
import pandas as pd
dic = {'a': 1,
'b': 2,
'c': 3,
'd': 4}
a = pd.Series(dic)
# 显示索引:直接用[], 使用loc
print(a['d'], a.loc['d'])
# 一次得到多个值
print(a[['a', 'd']])
print(a.loc[['a', 'd']])
"""
输出结果:
4 4
a 1
d 4
dtype: int64
a 1
d 4
dtype: int64
"""
2、隐式索引
①、使用整数作为索引值(隐式索引使用的是数值)
②、使用 .iloc[](推荐)
import pandas as pd
li = [1, 2, 3, 4]
a = pd.Series(li)
# 使用数字下标
print(a[0], a[[0]], a[[0, 3]], sep='\n')
# 使用iloc[]
print(a.iloc[0], a[[0]], a[[0, 3]], sep='\n')
"""
输入结果:
1
0 1
dtype: int64
0 1
3 4
dtype: int64
1
0 1
dtype: int64
0 1
3 4
dtype: int64
"""
Series的切片
这里的切片操作,分为显示切片和隐式切片两种。值得注意的是显示切片:左闭右闭,而隐式切片(隐式切片是使用使的数字下标)是左闭右开。
还可以使用loc[] 和 iloc[] 进行切片,不过要注意的是在显示的时候只能使用 loc[] ,但在隐式时使用什么都不会报错。
1、显示切片
import pandas as pd
# 显示的操作
dic = {'语文': 80,
'数学': 100,
'计算机': 100,
'政治': 90
}
a = pd.Series(dic)
print(a.loc['数学':'计算机'])
"""
输出结果:
数学 100
计算机 100
dtype: int64
"""
2、隐式切片
# 隐式的操作
import pandas as pd
dic = {1: 80,
2: 100,
3: 100,
4: 90
}
a = pd.Series(dic)
print(a[2:4])
print(a.loc[2:4])
print(a.iloc[2:4])
"""
输出结果:
3 100
4 90
dtype: int64
2 100
3 100
4 90
dtype: int64
3 100
4 90
dtype: int64
"""
Series 的基本属性和方法
1、基本的属性
(1)、shape形状
在Pandas库中,shape 是一个属性,它返回一个元组,表示DataFrame或Series的维度。
对于 Series:shape 返回一个元组,其中只有一个元素,即Series的长度(也称为索引的长度)
import pandas as pd
# 创建一个简单的Series
s = pd.Series([1, 2, 3, 4, 5])
print(s.shape) # 输出: (5,) 表示有5个元素
对于 DataFrame:shape 返回一个元组,其中第一个元素是行数(也称为索引的长度),第二个元素是列数(也称为列标签的数量)。
import pandas as pd
# 创建一个简单的DataFrame
df = pd.DataFrame({
'A': [1, 2, 3],
'B': [4, 5, 6],
'C': [7, 8, 9]
})
print(df.shape) # 输出: (3, 3) 表示有3行和3列
(2)、size长度
在Pandas中,size 属性与 shape 属性略有不同。对于DataFrame和Series,size 返回的是对象中元素的总数,而不是一个表示维度的元组。
size 返回的是Series中元素的数量,与 len() 的结果相同。
import pandas as pd
# 创建一个简单的Series
s = pd.Series([1, 2, 3, 4, 5])
print(s.size) # 输出: 5,因为有5个元素
对于 DataFrame:size 返回的是DataFrame中所有元素的数量,即行数乘以列数。
import pandas as pd
# 创建一个简单的DataFrame
df = pd.DataFrame({
'A': [1, 2, 3],
'B': [4, 5, 6],
'C': [7, 8, 9]
})
print(df.size) # 输出: 9,因为有3行和3列,总共9个元素
(3)、index索引
在Pandas中,index 属性是一个非常关键的概念,它用于表示DataFrame或Series中的行标签。对于DataFrame,它通常是一个 index 对象,包含了所有行的标签;对于Series,index 同样是一个index 对象,但在这里它表示的是每个数据点的标签。
import pandas as pd
# 创建一个简单的Series
s = pd.Series([1, 2, 3], index=['a', 'b', 'c'])
# 查看Series的index
print(s.index) # 输出: Index(['a', 'b', 'c'], dtype='object')
# 你可以通过索引标签来访问Series中的值
print(s['b']) # 输出: 2
当你创建一个DataFrame时,Pandas会自动为其分配一个默认的整数索引(从0开始),除非你在创建时指定了其他的索引。你可以通过df.index
来查看或操作DataFrame的索引。
import pandas as pd
# 创建一个简单的DataFrame
df = pd.DataFrame({
'A': [1, 2, 3],
'B': [4, 5, 6]
})
# 查看DataFrame的index
print(df.index) # 输出: RangeIndex(start=0, stop=3, step=1)
# 你可以通过赋值来修改index
df.index = ['x', 'y', 'z']
print(df)
# 输出:
# A B
# x 1 4
# y 2 5
# z 3 6
(4)、values值
在Pandas库中,values
属性通常与DataFrame或Series对象相关联,用于获取这些对象中的底层数据作为NumPy数组。
对于Series对象当你有一个Pandas Series对象时,你可以使用values
属性来获取其数据作为一维NumPy数组。
import pandas as pd
# 创建一个Series对象
s = pd.Series([1, 2, 3, 4, 5])
# 使用values属性获取NumPy数组
numpy_array = s.values
print(numpy_array) # 输出: array([1, 2, 3, 4, 5])
对于DataFrame对象对于DataFrame对象,values
属性将返回一个二维NumPy数组,其中包含了DataFrame中所有的数据。
import pandas as pd
# 创建一个DataFrame对象
df = pd.DataFrame({
'A': [1, 2, 3],
'B': [4, 5, 6],
'C': [7, 8, 9]
})
# 使用values属性获取NumPy数组
numpy_array = df.values
print(numpy_array)
"""
输出:
array([[1, 4, 7],
[2, 5, 8],
[3, 6, 9]])
"""
(5)、name名字
在Pandas库中,name
属性主要与Series
对象相关联,它用于存储该Series
的名称。这个属性在创建Series
时可以设置,或者后续通过赋值来更改。
import pandas as pd
# 创建一个带有name属性的Series
s = pd.Series([1, 2, 3, 4], name='my_series')
print(s)
# 输出:
# 0 1
# 1 2
# 2 3
# 3 4
# Name: my_series, dtype: int64
print(s.name) # 输出: my_series
2、基本方法
(1)、head()查看前几条数据,默认5条
import pandas as pd
dic = {'语文': 80,
'数学': 100,
'政治': 95,
'计算机': 99,
'历史': 99,
'物理': 95,
'化学': 95
}
a = pd.Series(dic)
print(a.head(3))
"""
输出
语文 80
数学 100
政治 95
dtype: int64
"""
(2)、tail()查看后几条数据,默认5条
import pandas as pd
dic = {'语文': 80,
'数学': 100,
'政治': 95,
'计算机': 99,
'历史': 99,
'物理': 95,
'化学': 95
}
a = pd.Series(dic)
print(a.tail(3))
"""
输出
历史 99
物理 95
化学 95
dtype: int64
"""
检测缺失数据的一些函数
(1)、pd.isnull()
pd.isnull()
函数接收一个或多个Pandas对象作为输入,并返回一个与输入对象形状相同的布尔对象,其中True
表示对应位置的值是缺失的,False
表示不是。
有两种方式:
①、a.isnull()
②、pd.isnull(a)
import pandas as pd
# 创建一个包含缺失值的Series
s = pd.Series([1, 2, None, 4])
# 使用.isnull()方法检测缺失值
print(s.isnull())
"""
输出
0 False
1 False
2 True
3 False
dtype: bool
"""
np.nan
经常用于表示缺失或无效的数据。
np.nan
有一些特殊的性质:
- 它不等于任何值,包括它自身。即
np.nan == np.nan
返回False
。 - 使用常规的算术操作符(如
+
、-
、*
、/
)对包含np.nan
的数组进行操作时,结果通常是np.nan
(除非进行的是位运算)。 np.isnan()
函数用于检测一个值是否是np.nan
.
import pandas as pd
import numpy as np
# 创建一个包含缺失值的Series
s = pd.Series([1, 2, np.nan, 4])
# 使用.isnull()方法检测缺失值
print(s.isnull())
"""
输出
0 False
1 False
2 True
3 False
dtype: bool
"""
(2)、pd.notnull()
在Pandas库中,pd.notnull()
函数与pd.isnull()
函数相对应,用于检测数据(如Series、DataFrame等)中的非缺失值。这个函数接收一个或多个Pandas对象作为输入,并返回一个与输入对象形状相同的布尔对象,其中True
表示对应位置的值不是缺失的,False
表示是缺失的。
import pandas as pd
import numpy as np
dic = {'a': 1,
'b': 2,
'c': np.nan,
'd': 4,
'e': np.nan
}
a = pd.Series(dic)
print(a.notnull())
"""
输出
a True
b True
c False
d True
e False
dtype: bool
"""
(3)、通过bool值索引过滤数据
可以利用上面的两个函数求出空置,利用布尔值把非空的数据进行筛选出来。
~布尔类型,这里的~表示取反。
import numpy as np
import pandas as pd
a = pd.Series([1, 2, np.nan, 4], index=list('abcd'))
ind = a.notnull()
print(a[ind]) # 这里当索引为False时不取此元素, 当为True时把此元素取出
Series的运算
1、适用于Numpy的数组运算也使用与Series
标量运算指的是 Series
与单个数值(标量)之间的运算。这种运算会对 Series
中的每个元素都应用相同的标量值。
标量运算:指的是一个Series
与一个数值进行运算,包括(+、 -、 *、 /、 //、 %、** 等)。
import pandas as pd
a = pd.Series([1, 2, 3, 4])
print(a * 100)
# 其他的预算与加法类似
2、Series之间的运算
①、在运算中自动对齐索引(根据索引来计算)
②、如果索引不对齐,则补充NaN
③、Series没有广播机制
import numpy as np
import pandas as pd
a = pd.Series([1, 2, 3, 4])
b = pd.Series([100, 100, 100, 100])
print(a + b)
# 对应索引来计算
a = pd.Series([1, 3, 4], index=[3, 2, 1])
b = pd.Series([1, 20, 30, 40])
print(a + b)
"""
输出
0 101
1 102
2 103
3 104
dtype: int64
0 NaN
1 24.0
2 33.0
3 41.0
"""
如果要保留索引的index, 则需要使用.add函数
import pandas as pd
a = pd.Series([1, 2, 3])
b = pd.Series([100, 100, 100, 100])
print(a.add(b, fill_value=0))
print(b.add(a, fill_value=0))
"""
输出
0 101.0
1 102.0
2 103.0
3 100.0
dtype: float64
0 101.0
1 102.0
2 103.0
3 100.0
dtype: float64
"""
总结:Series可以看做是一个有序的字典结构(也可以默认索引看做列表结构),在数据特别多的字典取值会更加的快。
DataFrame
DataFrame
是 Pandas 库中的一个核心数据结构,用于存储和操作二维的、大小可变且可以包含异构类型列的表格数据。你可以将 DataFrame
想象成一个电子表格或 SQL 表,或者一个字典对象,其中包含了多个序列(如 Series)对象。
DataFrame
是一个表格型的数据结构,可以看做是由Series组成的字典(公用一个索引)。DataFrame
阿么由按一定顺序排列的多数据组成。设计初衷是将Series的使用场景从一维拓展到多维。DataFrame
既有行索引,也有列索引。
①、行索引:index
②、列索引:columns
③、值:values(Nnumpy的二维数组)
DataFrame的创建
1、利用字典
import pandas as pd
dic = {'name': ['语', '数', '外'],
'age': [5000, 500, 50]
}
a = pd.DataFrame(dic)
print(a)
"""
输出
name age
0 语 5000
1 数 500
2 外 50
"""
DataFrame
的每一列表示一个属性。
DataFrame
的每一行表示一个样本,一条数组。
2、设置行索引修改列索引
import pandas as pd
dic = {'name': ['语', '数', '外'],
'age': [5000, 500, 50]
}
a = pd.DataFrame(dic, index=['a', 'b', 'c'])
print(a)
"""
输出
name age
a 语 5000
b 数 500
c 外 50
"""
3、利用二维列表或Numpy创建
import pandas as pd
li = [[i * j for i in range(1, 5)] for j in range(1, 5)]
a = pd.DataFrame(li, index=list('abcd'), columns=list("ABCD"))
print(a)
"""
输出
A B C D
a 1 2 3 4
b 2 4 6 8
c 3 6 9 12
d 4 8 12 16
"""
DataFrame的基本属性
1、values值,二维ndarry数组
这里的values属性和上面一维是一样的,不同之处是在这里是二维。
import pandas as pd
dic = {'name': ['语', '数', '外'],
'age': [5000, 500, 50]
}
a = pd.DataFrame(dic)
val = a.values
print(val)
"""
输出
[['语' 5000]
['数' 500]
['外' 50]]
"""
2、columns列索引
columns属性可以得到列索引。
import pandas as pd
dic = {'name': ['语', '数', '外'],
'age': [5000, 500, 50]
}
a = pd.DataFrame(dic)
print(a.columns)
print(list(a.columns))
"""
输出
Index(['name', 'age'], dtype='object')
['name', 'age']
"""
3、index行索引
上面介绍过一维时index 属性的使用,这里的使用方法与一维时完全相同。还可以利用index 来修改行索引。
import pandas as pd
dic = {'name': ['语', '数', '外'],
'age': [5000, 500, 50]
}
a = pd.DataFrame(dic)
print(a.index)
a.index = ['a', 'b', 'c']
print(a)
"""
输出
RangeIndex(start=0, stop=3, step=1)
name age
a 语 5000
b 数 500
c 外 50
"""
4、shape形状
这个属性蛮重要的,当数据较多时,可以通过shape 来看数组的行数和列数。
import pandas as pd
dic = {'name': ['语', '数', '外'],
'age': [5000, 500, 50]
}
a = pd.DataFrame(dic)
print(a.shape) # 输出: (3, 2) 表示3行2列
DataFrame的方法
1、head()产看前面的数据
head 在上面一维时说过, 与上面的使用方法完全一样。
import pandas as pd
li = [[i * j for i in range(1, 4)] for j in range(1, 10)]
a = pd.DataFrame(li, index=list('abcdefghi'), columns=list("ABC"))
# 查看前三行
print(a.head(3))
"""
输出
A B C
a 1 2 3
b 2 4 6
c 3 6 9
"""
2、tail()查看后面的数据
import pandas as pd
li = [[i * j for i in range(1, 4)] for j in range(1, 10)]
a = pd.DataFrame(li, index=list('abcdefghi'), columns=list("ABC"))
# 查看最后的三行
print(a.tail(3))
"""
输出
A B C
g 7 14 21
h 8 16 24
i 9 18 27
"""
DataFrame的索引
1、对列进行索引
①、通过类似的字典方式
②、通过属性的方式
可以将DataFrame的列获取为一个Series。返回的Series 拥有DataFrame 相同的索引, 且name属性也已经设置好了,就是响应的列名。
import pandas as pd
li = [[i * j for i in range(1, 5)] for j in range(1, 5)]
a = pd.DataFrame(li, index=['小明', '小红', '小黄', '小蓝'], columns=['数学', '化学', '英语', '历史'])
print(a.数学, a['数学'], sep='\n')
"""
输出
小明 1
小红 2
小黄 3
小蓝 4
Name: 数学, dtype: int64
小明 1
小红 2
小黄 3
小蓝 4
Name: 数学, dtype: int64
"""
同时取出多列 使用两个[[]] 来同时取出多列
import pandas as pd
li = [[i * j for i in range(1, 5)] for j in range(1, 5)]
a = pd.DataFrame(li, index=['小明', '小红', '小黄', '小蓝'], columns=['数学', '化学', '英语', '历史'])
print(a[['数学', '历史']])
"""
输出
数学 历史
小明 1 4
小红 2 8
小黄 3 12
小蓝 4 16
"""
2、对行进行索引
①、使用.loc[]加index 来进行行索引
②、使用.iloc[]加整数来进行行索引(使用数字索引)
同时返回一个Series, index 为原来的columns。
import pandas as pd
li = [[i * j for i in range(1, 5)] for j in range(1, 5)]
a = pd.DataFrame(li, index=['小明', '小红', '小黄', '小蓝'], columns=['数学', '化学', '英语', '历史'])
print(a.loc[['小明', '小蓝']])
"""
输出
数学 化学 英语 历史
小明 1 2 3 4
小蓝 4 8 12 16
"""
3、对元素索引
①、使用列索引
②、使用行索引
③、使用values 属性(二维Numpy数组)
import pandas as pd
li = [[i * j for i in range(1, 5)] for j in range(1, 5)]
a = pd.DataFrame(li, index=['小明', '小红', '小黄', '小蓝'], columns=['数学', '化学', '英语', '历史'])
# 先取列后取行
print(a['数学']['小明'])
# 先取行后取列
print(a.loc['小明']['历史'])
# []中间使用逗号
print(a.iloc[1, 3])
注意:这里的取值特别特别多,上面只写了一小部分
DataFrame的切片
直接用中括号时;
①、索引优先对列进行操作
②、切片优先对行进行操作
行切片,在进行切片时显示切片时左闭右闭, 隐式时左闭右开
import pandas as pd
li = [[i * j for i in range(1, 5)] for j in range(1, 5)]
a = pd.DataFrame(li, index=['小明', '小红', '小黄', '小蓝'], columns=['数学', '化学', '英语', '历史'])
# 行切片
print(a['小明':'小黄'])
"""
输出
数学 化学 英语 历史
小明 1 2 3 4
小红 2 4 6 8
小黄 3 6 9 12
"""
列切片,对列切片的时候,也必须先对行切片,在列切片的时候必须使用loc。
import pandas as pd
li = [[i * j for i in range(1, 5)] for j in range(1, 5)]
a = pd.DataFrame(li, index=['小明', '小红', '小黄', '小蓝'], columns=['数学', '化学', '英语', '历史'])
# 列切片
print(a.loc[:, '数学':'化学'])
"""
输出
数学 化学
小明 1 2
小红 2 4
小黄 3 6
小蓝 4 8
"""
同时对行和列进行切片,先对行切片,再对列切片。
import pandas as pd
li = [[i * j for i in range(1, 5)] for j in range(1, 5)]
a = pd.DataFrame(li, index=['小明', '小红', '小黄', '小蓝'], columns=['数学', '化学', '英语', '历史'])
# 行列切片
print(a.loc['小明':'小红', '数学':'化学'])
"""
输出
数学 化学
小明 1 2
小红 2 4
"""
索引和切片混合使用
import pandas as pd
li = [[i * j for i in range(1, 5)] for j in range(1, 5)]
a = pd.DataFrame(li, index=['小明', '小红', '小黄', '小蓝'], columns=['数学', '化学', '英语', '历史'])
# 行列切片
print(a.loc['小明':'小红', ['数学']])
print(a.loc[['小明', '小黄'], '数学':'历史'])
"""
输出
数学
小明 1
小红 2
数学 化学 英语 历史
小明 1 2 3 4
小黄 3 6 9 12
"""
总结:切片的方式多种多样,可以使用显示(loc, 左闭右闭)切片,也可以使用隐式(iloc, 左闭右开)切片。切片和索引可以混合使用,这里的切片和索引由于方法太多较为复杂。需要多去练习。
①、要么取一行或一列:索引
②、要么取连续的多行或多列:切片
③、要么取不连续的多行或多列:中括号
DataFrame的运算
①、在运算中自动对齐不同索引的数据
②、如果索引不对应,则补NaN
③、DataFrame没有广播机制
1、DataFrame和标量之间的运算
DataFrame和标量之间的运算包括(+、 -、 *、/、 //、 % 、 **)等。
import pandas as pd
li = [[i * j for i in range(1, 5)] for j in range(1, 5)]
a = pd.DataFrame(li, index=['小明', '小红', '小黄', '小蓝'], columns=['数学', '化学', '英语', '历史'])
print(a + 100)
print(a ** 5)
2、DataFrame之间的运算
在运算过程中对应索引来计算,如果两个二维的数组不完全相同,则无法对应的索引一行或一列用NaN填充。
import pandas as pd
li = [[i * j for i in range(1, 5)] for j in range(1, 5)]
a = pd.DataFrame(li, index=['小明', '小红', '小黄', '小蓝'], columns=['数学', '化学', '英语', '历史'])
b = pd.DataFrame(li, index=['小明', '小红', '小黄', '小蓝'], columns=['数学', '化学', '英语', '历史'])
print(a * b)
"""
数学 化学 英语 历史
小明 1 4 9 16
小红 4 16 36 64
小黄 9 36 81 144
小蓝 16 64 144 256
"""
import pandas as pd
li = [[i * j for i in range(1, 5)] for j in range(1, 5)]
a = pd.DataFrame(li, index=['小明', '小红', '小黄', '小蓝'], columns=['数学', '化学', '英语', '历史'])
li = [[i * j for i in range(1, 5)] for j in range(1, 4)]
b = pd.DataFrame(li, index=['小明', '小红', '小蓝'], columns=['数学', '化学', '英语', '历史'])
print(a * b)
"""
数学 化学 英语 历史
小明 1.0 4.0 9.0 16.0
小红 4.0 16.0 36.0 64.0
小蓝 12.0 48.0 108.0 192.0
小黄 NaN NaN NaN NaN
"""
3、使用add来填充
import pandas as pd
li = [[i * j for i in range(1, 5)] for j in range(1, 5)]
a = pd.DataFrame(li, index=['小明', '小红', '小黄', '小蓝'], columns=['数学', '化学', '英语', '历史'])
li = [[i * j for i in range(1, 5)] for j in range(1, 4)]
b = pd.DataFrame(li, index=['小明', '小红', '小蓝'], columns=['数学', '化学', '英语', '历史'])
print(a.add(b, fill_value=0))
"""
数学 化学 英语 历史
小明 2.0 4.0 6.0 8.0
小红 4.0 8.0 12.0 16.0
小蓝 7.0 14.0 21.0 28.0
小黄 3.0 6.0 9.0 12.0
"""
4、divide()除法
a.divide(b, fill_value = s) 表示a 除以 b 当b为NaN时进行填充s。
import pandas as pd
li = [[i * j for i in range(1, 5)] for j in range(1, 5)]
a = pd.DataFrame(li, index=['小明', '小红', '小黄', '小蓝'], columns=['数学', '化学', '英语', '历史'])
li = [[i * j for i in range(1, 5)] for j in range(1, 4)]
b = pd.DataFrame(li, index=['小明', '小红', '小蓝'], columns=['数学', '化学', '英语', '历史'])
# 表示的是a / b
print(a.divide(b, fill_value=1))
"""
数学 化学 英语 历史
小明 1.000000 1.000000 1.000000 1.000000
小红 1.000000 1.000000 1.000000 1.000000
小蓝 1.333333 1.333333 1.333333 1.333333
小黄 3.000000 6.000000 9.000000 12.000000
"""
5、Series与DataFrame之间的运算
①、使用Python操作符:以行为单位操作(参数必须是行),对所有行都有效。
类似于NUmPy中的二维数组与一维数组的运算,但可能出现NaN
②、使用Pandas操作函数:
- axis = 0:以列为单位操作(参数必须是列),对所有列都有效。
- axis = 1:以行为单位操作(参数必须是行),对所有行都有效。
import pandas as pd
li = [[i * j for i in range(1, 5)] for j in range(1, 5)]
a = pd.DataFrame(li, index=['小明', '小红', '小黄', '小蓝'], columns=['数学', '化学', '英语', '历史'])
b = pd.Series([100, 50, 10, 1], index=a.columns)
print(a + b)
"""
数学 化学 英语 历史
小明 101 52 13 5
小红 102 54 16 9
小黄 103 56 19 13
小蓝 104 58 22 17
"""
a = pd.DataFrame(li, index=['小明', '小红', '小黄', '小蓝'], columns=['数学', '化学', '英语', '历史'])
b = pd.Series([100, 50, 10, 1], index=a.index)
print(a.add(b, axis=0))
"""
数学 化学 英语 历史
小明 101 102 103 104
小红 52 54 56 58
小黄 13 16 19 22
小蓝 5 9 13 17
"""
Pandas层次化索引
创建多层行索引
1、隐式构造
最常见的方法是给DataFrame构造函数的鹅index 参数传递两个或者更多的数组
DataFrame构造多层索引,当连续的多个名字是一样的的时候,只显示一个索引。
import pandas as pd
li = [[i * j for i in range(1, 5)] for j in range(1, 5)]
ind = [['一班', '一班', '二班', '二班'],
['小明', '小红', '小黄', '小蓝']]
col = [['理科', '理科', '文科', '文科'],
['数学', '化学', '英语', '历史']]
a = pd.DataFrame(li, index=ind, columns=col)
print(a)
"""
理科 文科
数学 化学 英语 历史
一班 小明 1 2 3 4
小红 2 4 6 8
二班 小黄 3 6 9 12
小蓝 4 8 12 16
"""
Series构造多层索引,和上面的DataFrame类似。
import pandas as pd
ind = [['一班', '一班', '二班', '二班'],
['小明', '小红', '小黄', '小蓝']]
a = pd.Series([100, 85, 90, 100], index=ind)
print(a)
"""
一班 小明 100
小红 85
二班 小黄 90
小蓝 100
dtype: int64
"""
2、显示构造pd.Multilndex
(1)、使用数组
在index 创建数组的时候比上面的的更为复杂。使用了 pd.MultiIndex.from_arrays。
import pandas as pd
li = [[i * j for i in range(1, 5)] for j in range(1, 5)]
ind = pd.MultiIndex.from_arrays([['一班', '一班', '二班', '二班'],
['小明', '小红', '小黄', '小蓝']])
col = [['理科', '理科', '文科', '文科'],
['数学', '化学', '英语', '历史']]
a = pd.DataFrame(li, index=ind, columns=col)
print(a)
"""
理科 文科
数学 化学 英语 历史
一班 小明 1 2 3 4
小红 2 4 6 8
二班 小黄 3 6 9 12
小蓝 4 8 12 16
"""
(2)、使用tuple
这种方法使用了pd.MultiIndex.from_tuples。
import pandas as pd
li = [[i * j for i in range(1, 5)] for j in range(1, 5)]
ind = pd.MultiIndex.from_tuples([('一班', '小明'), ('一班', '小红'),
('二班', '小黄'), ('二班', '小蓝')])
# ['一班', '一班', '二班', '二班'],
# ['小明', '小红', '小黄', '小蓝']
col = [['理科', '理科', '文科', '文科'],
['数学', '化学', '英语', '历史']]
a = pd.DataFrame(li, index=ind, columns=col)
print(a)
"""
理科 文科
数学 化学 英语 历史
一班 小明 1 2 3 4
小红 2 4 6 8
二班 小黄 3 6 9 12
小蓝 4 8 12 16
"""
(3)、使用product笛卡尔积
不是所有的都可以使用笛卡尔积
import pandas as pd
li = [[i * j for i in range(1, 5)] for j in range(1, 5)]
ind = pd.MultiIndex.from_product([['一班', '二班'],
['小明', '小红']])
col = [['理科', '理科', '文科', '文科'],
['数学', '化学', '英语', '历史']]
a = pd.DataFrame(li, index=ind, columns=col)
print(a)
"""
理科 文科
数学 化学 英语 历史
一班 小明 1 2 3 4
小红 2 4 6 8
二班 小明 3 6 9 12
小红 4 8 12 16
"""
上面的只给出了行索引的例子, 在列索引上同样适用。
多层索引对象的索引与切片操作
1、Series的操作
对于Series来说,直接中括号 [ ] 与使用.loc 完全一样。
(1)、索引
①、显示索引
在多层索引的时候先取外面的层,在取出里面的层,这里的显示索引多种多样,使用的方法特别多需要多加练习。
# import pandas as pd
#
# li = [[i * j for i in range(1, 5)] for j in range(1, 5)]
# ind = [['一班', '一班', '二班', '二班'],
# ['小明', '小红', '小黄', '小蓝']]
# col = [['理科', '理科', '文科', '文科'],
# ['数学', '化学', '英语', '历史']]
# a = pd.DataFrame(li, index=ind, columns=col)
#
# print(a)
import pandas as pd
li = [j for j in range(1, 5)]
ind = [['一班', '一班', '二班', '二班'],
['小明', '小红', '小黄', '小蓝']]
a = pd.Series(li, index=ind)
print(a['一班'])
print(a.loc['一班']['小红'])
# 可以只使用一个中括号中间使用逗号隔开
print(a.loc['一班', '小红'])
"""
小明 1
小红 2
dtype: int64
2
2
"""
②、隐式索引
利用隐式索引来取值相对于使用显示索引要简单,建议使用 .iloc来进行隐式索引。
import pandas as pd
li = [j for j in range(1, 5)]
ind = [['一班', '一班', '二班', '二班'],
['小明', '小红', '小黄', '小蓝']]
a = pd.Series(li, index=ind)
print(a.iloc[[1, 0]])
print(a.iloc[1])
"""
一班 小红 2
小明 1
dtype: int64
2
"""
(2)、切片
①、显示切片
在显示切片中,是左闭右闭的,在切片过程中不能直接对内层直接前切片。以下面的例子为例即不能跨班级切片。
import pandas as pd
li = [j for j in range(1, 5)]
ind = [['一班', '一班', '二班', '二班'],
['小明', '小红', '小黄', '小蓝']]
a = pd.Series(li, index=ind)
print(a['一班':'二班'])
print(a.loc['一班':'二班'])
print(a.loc['一班'][:])
"""
一班 小明 1
小红 2
二班 小黄 3
小蓝 4
dtype: int64
一班 小明 1
小红 2
二班 小黄 3
小蓝 4
dtype: int64
小明 1
小红 2
dtype: int64
"""
②、隐式切片
在多层索引中更加推荐的是隐式切片,不需要考虑外层的索引,可以直接跨外层索引对内层进行切片。
这里的隐式切片更为简单但是需要注意的是隐式切片是左闭右开。
import pandas as pd
li = [j for j in range(1, 5)]
ind = [['一班', '一班', '二班', '二班'],
['小明', '小红', '小黄', '小蓝']]
a = pd.Series(li, index=ind)
print(a.iloc[1:3])
"""
一班 小红 2
二班 小黄 3
dtype: int64
"""
2、DataFrame操作
(1)、索引
①、获取元素
如果不使用函数 .loc 和 .iloc 时,则先取出的是列,如果使用则先取的是行。
import pandas as pd
li = [[i * j for i in range(1, 5)] for j in range(1, 5)]
ind = [['一班', '一班', '二班', '二班'],
['小明', '小红', '小黄', '小蓝']]
col = [['理科', '理科', '文科', '文科'],
['数学', '化学', '英语', '历史']]
a = pd.DataFrame(li, index=ind, columns=col)
print(a)
# 显示索引
print(a['理科']['数学']['二班']['小蓝'])
print(a[('理科', '数学')]['二班', '小蓝'])
# 隐式索引
print(a.iloc[1, 1])
②、列索引
直接使用中括号的情况下则说明是默认先取出列,如果使用 .col 或 .iloc 函数是则先取出的是行
import pandas as pd
li = [[i * j for i in range(1, 5)] for j in range(1, 5)]
ind = [['一班', '一班', '二班', '二班'],
['小明', '小红', '小黄', '小蓝']]
col = [['理科', '理科', '文科', '文科'],
['数学', '化学', '英语', '历史']]
a = pd.DataFrame(li, index=ind, columns=col)
print(a['理科']['数学'])
print(a['理科', '数学'])
print(a['理科'][['数学']])
"""
一班 小明 1
小红 2
二班 小黄 3
小蓝 4
Name: 数学, dtype: int64
一班 小明 1
小红 2
二班 小黄 3
小蓝 4
Name: (理科, 数学), dtype: int64
数学
一班 小明 1
小红 2
二班 小黄 3
小蓝 4
"""
③、行索引
import pandas as pd
li = [[i * j for i in range(1, 5)] for j in range(1, 5)]
ind = [['一班', '一班', '二班', '二班'],
['小明', '小红', '小黄', '小蓝']]
col = [['理科', '理科', '文科', '文科'],
['数学', '化学', '英语', '历史']]
a = pd.DataFrame(li, index=ind, columns=col)
print(a.loc['一班'].loc['小明'])
"""
理科 数学 1
化学 2
文科 英语 3
历史 4
"""
(2)、切片
①、对行进行切片
import pandas as pd
li = [[i * j for i in range(1, 5)] for j in range(1, 5)]
ind = [['一班', '一班', '二班', '二班'],
['小明', '小红', '小黄', '小蓝']]
col = [['理科', '理科', '文科', '文科'],
['数学', '化学', '英语', '历史']]
a = pd.DataFrame(li, index=ind, columns=col)
print(a.loc["一班":])
print(a.iloc[1:3])
"""
理科 文科
数学 化学 英语 历史
一班 小明 1 2 3 4
小红 2 4 6 8
二班 小黄 3 6 9 12
小蓝 4 8 12 16
理科 文科
数学 化学 英语 历史
一班 小红 2 4 6 8
二班 小黄 3 6 9 12
"""
②、对列进行切片
import pandas as pd
li = [[i * j for i in range(1, 5)] for j in range(1, 5)]
ind = pd.MultiIndex.from_arrays([['一班', '一班', '二班', '二班'],
['小明', '小红', '小黄', '小蓝']])
col = pd.MultiIndex.from_arrays([['理科', '理科', '文科', '文科'],
['数学', '化学', '英语', '历史']])
a = pd.DataFrame(li, index=ind, columns=col)
print(a.iloc[1:3, 1:3])
"""
理科 文科
化学 英语
一班 小红 4 6
二班 小黄 6 9
"""
上一个来介绍Pandas 的文章太长了,在这里续一下下面的内容
索引的堆叠
①、stack()
②、unstack()
1、stack()
使用stack() 的作用是将列索引变为行索引,默认是将最里层的列索引变为行索引。小技巧:使用stack() 的时候,level的等于哪一个, 哪一个就消失,出现在列里。
import pandas as pd
li = [[i * j for i in range(1, 5)] for j in range(1, 5)]
ind = pd.MultiIndex.from_arrays([['一班', '一班', '二班', '二班'],
['小明', '小红', '小黄', '小蓝']])
col = pd.MultiIndex.from_arrays([['理科', '理科', '文科', '文科'],
['数学', '化学', '英语', '历史']])
a = pd.DataFrame(li, index=ind, columns=col)
# 默认的将最里层变为行索引
# 从外往里面依次是0 ~ n-1
# 这里的属性level 默认为-1
print(a.stack(level=-1))
"""
理科 文科
一班 小明 化学 2.0 NaN
历史 NaN 4.0
数学 1.0 NaN
英语 NaN 3.0
小红 化学 4.0 NaN
历史 NaN 8.0
数学 2.0 NaN
英语 NaN 6.0
二班 小黄 化学 6.0 NaN
历史 NaN 12.0
数学 3.0 NaN
英语 NaN 9.0
小蓝 化学 8.0 NaN
历史 NaN 16.0
数学 4.0 NaN
英语 NaN 12.0
"""
2、unstack()
使用unstack 是将行索引变为列索引,和上面的使用方法类似。
import pandas as pd
li = [[i * j for i in range(1, 5)] for j in range(1, 5)]
ind = pd.MultiIndex.from_arrays([['一班', '一班', '二班', '二班'],
['小明', '小红', '小黄', '小蓝']])
col = pd.MultiIndex.from_arrays([['理科', '理科', '文科', '文科'],
['数学', '化学', '英语', '历史']])
a = pd.DataFrame(li, index=ind, columns=col)
# 默认的将最里层变为行索引
# 从外往里面依次是0 ~ n-1
# 这里的属性level 默认为-1
# fill_value = 0; 是为填充为NaN的地方
print(a.unstack(level=-1, fill_value=0))
"""
理科 文科
数学 化学 英语 历史
小明 小红 小蓝 小黄 小明 小红 小蓝 小黄 小明 小红 小蓝 小黄 小明 小红 小蓝 小黄
一班 1 2 0 0 2 4 0 0 3 6 0 0 4 8 0 0
二班 0 0 4 3 0 0 8 6 0 0 12 9 0 0 16 12
"""
聚合操作
DataFrame就和函数
①、求和
②、平均值
③、最大值
④、最小值等
1、sum求和
sum中有一个属性axis默认是等于0的。
import pandas as pd
ind = ['张三', '李四', '王五']
col = ['数学', '语文', '英语']
li = [[10, 10, 10], [80, 80, 80], [90, 90, 90]]
a = pd.DataFrame(li, index=ind, columns=col)
print(a.sum()) # 默认axis = 0,求每一列多行的值。
print(a.values.sum()) # 求出表格中的所有的数的总和
print(a.sum(axis=1)) # 当axis = 1,求每一行多列的值
2、mean平均值
这个求平均值和上面的sum其实相同也有一个axis 属性,重点还是这和属性的运用,包括下面提到的和上面的用法几乎相同,只是表现的意义不同。为了完整,下面只会写一下代码。
import pandas as pd
ind = ['张三', '李四', '王五']
col = ['数学', '语文', '英语']
li = [[10, 10, 10], [80, 80, 80], [90, 90, 90]]
a = pd.DataFrame(li, index=ind, columns=col)
print(a.mean())
print(a.mean(axis=1))
3、max最大值
import pandas as pd
ind = ['张三', '李四', '王五']
col = ['数学', '语文', '英语']
li = [[10, 10, 10], [80, 80, 80], [90, 90, 90]]
a = pd.DataFrame(li, index=ind, columns=col)
print(a.max())
print(a.max(axis=1))
4、min最小值
import pandas as pd
ind = ['张三', '李四', '王五']
col = ['数学', '语文', '英语']
li = [[10, 10, 10], [80, 80, 80], [90, 90, 90]]
a = pd.DataFrame(li, index=ind, columns=col)
print(a.min())
print(a.min(axis=1))
5、多层索引中的聚合操作
当多层索引求聚合时,多了一个属性 level来控制对那一层进行聚合,对那一层则保留那一层的索引。索引从外往里面数 0 ~ n - 1。默认为-1。
import pandas as pd
li = [[i * j for i in range(1, 5)] for j in range(1, 5)]
ind = pd.MultiIndex.from_arrays([['一班', '一班', '二班', '二班'],
['小明', '小红', '小黄', '小蓝']])
col = pd.MultiIndex.from_arrays([['理科', '理科', '文科', '文科'],
['数学', '化学', '英语', '历史']])
a = pd.DataFrame(li, index=ind, columns=col)
print(a.sum())
print(a.sum(axis=1))
print(a.sum(axis=0, level=0))
"""
理科 数学 10
化学 20
文科 英语 30
历史 40
dtype: int64
一班 小明 10
小红 20
二班 小黄 30
小蓝 40
dtype: int64
理科 文科
数学 化学 英语 历史
一班 3 6 9 12
二班 7 14 21 28
"""
Pandas数据合并
在Pandas中,数据合并(Data Merging)或连接(Joining)是非常常见的操作。Pandas提供了几种方法来合并数据,最常用的是pd.merge()
函数,但也可以使用concat()
函数来堆叠数据。
1、使用pd.concat() 级联
这个 pd.concat() 默认情况下是上下和并,也就是说按照列索进行和并,如果列索引不完全相同则取列索引的并集。也可以根 axis 属性来改变合并的方向。
import pandas as pd
def f(ind, col):
li = [[] for _ in range(len(ind))]
for i in range(len(ind)):
for j in col:
li[i].append(ind[i] + j)
df = pd.DataFrame(data=li, index=ind, columns=col)
return df
df1 = f(list("AB"), list('12'))
df2 = f(list("AB"), list('23'))
print(df1, df2, sep='\n')
print(pd.concat([df1, df2]))
print(pd.concat([df1, df2], axis=1))
'''
1 2
A A1 A2
B B1 B2
2 3
A A2 A3
B B2 B3
1 2 3
A A1 A2 NaN
B B1 B2 NaN
A NaN A2 A3
B NaN B2 B3
1 2 2 3
A A1 A2 A2 A3
B B1 B2 B2 B3
'''
(1)、ignore_index属性
表示忽略行索引并重置索引
import pandas as pd
def f(ind, col):
li = [[] for _ in range(len(ind))]
for i in range(len(ind)):
for j in col:
li[i].append(ind[i] + j)
df = pd.DataFrame(data=li, index=ind, columns=col)
return df
df1 = f(list("AB"), list('12'))
df2 = f(list("CD"), list('12'))
# ignore_index=True : 表示忽略行索引,并重置
print(pd.concat([df1, df2], ignore_index=True))
"""
1 2
0 A1 A2
1 B1 B2
2 C1 C2
3 D1 D2
"""
(2)、使用多层索引keys
import pandas as pd
def f(ind, col):
li = [[] for _ in range(len(ind))]
for i in range(len(ind)):
for j in col:
li[i].append(ind[i] + j)
df = pd.DataFrame(data=li, index=ind, columns=col)
return df
df1 = f(list("AB"), list('12'))
df2 = f(list("CD"), list('12'))
# ignore_index=True : 表示忽略行索引,并重置
print(pd.concat([df1, df2], keys=['x', 'y']))
"""
1 2
x A A1 A2
B B1 B2
y C C1 C2
D D1 D2
"""
(3)、不匹配级联
不匹配指的是级联的维度的索引不一致,例如纵向级联时列索引不一致,横向