一、 什么是Pandas?
Pandas的名称来自于面板数据(panel data),Pandas是一个强大的分析结构化数据的工具集,基于NumPy构建,提供了高级数据结构和数据操作工具,它是使Python成为强大而高效的数据分析环境的重要因素之一。Pandas有以下几个特点:
- 是一个强大的分析和操作大型结构化数据集所需的工具集
- 基础是NumPy,提供了高性能矩阵的运算
- 提供了大量能够快速便捷地处理数据的函数和方法
- 应用于数据挖掘,数据分析
- 提供数据清洗功能
二、为什么要学习pandas
numpy已经能够帮助我们处理数据,能够结合matplotlib解决我们数据分析的问题,那么pandas学习的目的在什么地方呢?
numpy虽能够处理数值型数据,但是很多时候数据除了数值之外,还需要处理字符串、时间序列等。比如:我们通过爬虫获取到了存储在数据库中的数据,所以,pandas出现了。
pandas官网:https://pandas.pydata.org/,首先先来认识pandas中的两个常用的类
- Series(一维数据)
- DataFrame(二维数据)
三、Series
3.1 Series的创建
Series是一个一维的结构,创建Series的语法:
pd.Series();
常用的几个参数:
- index,用于指定新的索引,例如pd.Series(arr1,index=[‘a’,‘b’,‘c’,‘d’,‘e’])以a,b,c,d,e作为行索引;
- dtype,用于指定元素的数据类型;
3.1.1 通过列表或者一维数组创建
import numpy as np
import pandas as pd
# 1.通过list创建一维数组
s1 = pd.Series([1, 2, 3, 4, 5])
print(s1)
"""
0 1
1 2
2 3
3 4
4 5
dtype: int64
"""
# 2.通过numpy一维数组创建,pandas一维数组
arr = np.arange(1, 6)
s2 = pd.Series(arr)
print(s2)
"""
0 1
1 2
2 3
3 4
4 5
dtype: int32
"""
3.1.2 通过字典创建
import pandas as pd
dt = {'name': '范闲', 'age': 16, 'sex': '男'}
s3 = pd.Series(dt)
print(s3)
"""
name 范闲
age 16
sex 男
dtype: object
"""
# 通过字典创建数组的时候也可以指定索引,索引和字典键相同才有效,否则默认为 NaN
s4 = pd.Series(dt,index=['name', 'age', 'sex', 'class'])
print(s4)
"""
name 范闲
age 16
sex 男
class NaN
dtype: object
"""
3.2 Series的基本用法
3.2.1.Series常用属性
Series的常用属性:
- shape 返回形状
- size 返回元素个数
- index 返回索引值
- values 返回值
- dtype 元素的类型
用法示例:
import pandas as pd
# 创建pandas.Series对象
s = pd.Series(data=[1, 2, 3, 4, 'five'], index=['a', 'b', 'c', 'd', 'e'])
print(s.shape) # 返回形状:(5,)
print(s.dtype) # 返回元素类型:object
print(s.size) # 返回元素个数: 5
print(s.index) # 返回索引值: Index(['a', 'b', 'c', 'd', 'e'], dtype='object')
print(s.values) # 返回值: [1 2 3 4 'five']
3.2.2.索引取值
Series和DataFrame中的索引都是Index对象,索引对象不可变,保证了数据的安全。常见的Index种类:
- Index,索引
- Int64Index,整数索引
- MultiIndex,层级索引
- DatetimeIndex,时间戳类型
import pandas as pd
dt = {'name': '范闲', 'age': 16, 'sex': '男'}
s3 = pd.Series(dt)
print(s3)
"""
name 范闲
age 16
sex 男
dtype: object
"""
# 根据索引取值,使用 s3[0] 按位置访问元素的方法已被弃用,使用会报提示
# print(s3[0])
# 现在推荐使用.iloc 方法按位置访问元素
print(s3.iloc[0]) # 范闲
print(s3.iloc[0:2])
"""
name 范闲
age 16
dtype: object
"""
3.2.3.Series的常用方法:
⑴.head() 和 tail():
-
head(n)
: 返回前n
个元素,默认是 5 个。 -
tail(n)
: 返回后n
个元素,默认是 5 个。
import pandas as pd
s = pd.Series([1, 2, 3, 4, 5, 6])
print(s.head(3)) # 输出前 3 个元素
"""
0 1
1 2
2 3
dtype: int64
"""
print(s.tail(3)) # 输出后 3 个元素
"""
3 4
4 5
5 6
dtype: int64
"""
⑵.unique():
- 返回
Series
中唯一值的数组。
import pandas as pd
s2 = pd.Series([1, 2, 2, 3, 4, 4, 5])
print(s2.unique()) # 输出: [1 2 3 4 5]
⑶.isnull() 和 notnull():
-
isnull()
: 检查Series
中是否有缺失值,返回一个布尔Series
。 -
notnull()
: 检查Series
中是否没有缺失值,返回一个布尔Series
。
import pandas as pd
s = pd.Series([1, 2, None, 4, None])
print(s.isnull()) # 输出: [False False True False True]
print(s.notnull()) # 输出: [ True True False True False]
⑷.add()、sub()、mul()、div():
这些方法用于按元素执行算术运算:
-
add()
: 加法 -
sub()
: 减法 -
mul()
: 乘法 -
div()
: 除法
import pandas as pd
s1 = pd.Series([1, 2, 3])
s2 = pd.Series([4, 5, 6])
print(s1.add(s2)) # 输出: [5, 7, 9]
print(s1.sub(s2)) # 输出: [-3, -3, -3]
print(s1.mul(s2)) # 输出: [4, 10, 18]
print(s1.div(s2)) # 输出: [0.25, 0.4, 0.5]
3.2.4.Series的算术运算:
在 pandas.Series
中进行算术运算时,确保了索引一致的元素会进行算数运算,而对于不一致的索引,则会补空(NaN)。这种处理方式称为对齐(alignment)。举例来说,假设有两个 Series
对象 s1
和 s2
:
import pandas as pd
s1 = pd.Series([1, 2, 3], index=['a', 'b', 'c'])
s2 = pd.Series([4, 5, 6], index=['b', 'c', 'd'])
# 算术运算时,对齐索引进行操作,不一致的索引会补空(NaN)
result = s1 + s2
print(result)
"""
result输出:
a NaN
b 6.0
c 8.0
d NaN
dtype: float64
"""
解释一下这个结果:
-
s1
中的索引有'a', 'b', 'c'
,而s2
中的索引有'b', 'c', 'd'
。 - 在进行加法运算时,对应的索引
'b'
和'c'
对应的元素分别是2
和3
,所以结果为2 + 4 = 6
和3 + 5 = 8
。 - 对于索引
'a'
和'd'
,因为只存在于其中一个Series
中,所以在结果中显示为NaN
(空值)。
这种对齐操作使得 pandas.Series
在处理数据时非常灵活和方便,特别是在处理来自不同数据源或者部分缺失数据的情况下,能够保证结果的一致性和可靠性。
四、DataFrame
DataFrame
是一个【表格型】的数据结构。DataFrame
由按一定顺序排列的多列数据组成。设计初衷是将 Series
的使用场景从一维扩展到二维。在 DataFrame
中,每一列可以是不同的数据类型(例如整数、浮点数、字符串等),且每一列本质上是一个 Series
。DataFrame
可以看作是共享同一个索引的多个 Series
组成的结构。
主要特点:
- 二维数据结构:
DataFrame
是二维的,可以看作一个电子表格或 SQL 表。 - 按标签或整数索引:可以通过标签(列名)或整数索引访问数据。
- 不同数据类型的列:每一列可以是不同的数据类型。
4.1.DateFrame创建
4.1.1.字典类
import numpy as np
import pandas as pd
# 数组、列表或元组构成的字典构造dataframe
# 注意:所有数组的长度必须相同
data = {
"a": [1, 2, 3, 4, 5],
"b": (5, 6, 7, 8, 9),
"c": np.arange(9, 14)
}
# 构造dataframe
df = pd.DataFrame(data)
print(df)
"""
a b c
0 1 5 9
1 2 6 10
2 3 7 11
3 4 8 12
4 5 9 13
"""
上面结果发现:DataFrame既有行索引,也有列索引。
- 行索引:index
- 列索引:columns
- 值:values
import numpy as np
import pandas as pd
# 数组、列表或元组构成的字典构造dataframe
# 注意:所有数组的长度必须相同
data = {
"a": [1, 2, 3, 4, 5],
"b": (5, 6, 7, 8, 9),
"c": np.arange(9, 14)
}
# 构造dataframe
df = pd.DataFrame(data)
"""
a b c
0 1 5 9
1 2 6 10
2 3 7 11
3 4 8 12
4 5 9 13
"""
# index属性查看行索引
print(df.index) # RangeIndex(start=0, stop=5, step=1)
# columns属性查看列索引
print(df.columns) # Index(['a', 'b', 'c'], dtype='object')
# values属性查看值
print(df.values)
"""
[[ 1 5 9]
[ 2 6 10]
[ 3 7 11]
[ 4 8 12]
[ 5 9 13]]
"""
# 指定index
df2 = pd.DataFrame(data, index=['A', 'B', 'C', 'D', 'E'])
print(df2)
"""
a b c
A 1 5 9
B 2 6 10
C 3 7 11
D 4 8 12
E 5 9 13
"""
4.1.2.列表类
import numpy as np
import pandas as pd
# Series构成的字典构造dataframe
dt = pd.DataFrame({'a': pd.Series(np.arange(3)), 'b': pd.Series(np.arange(3, 5))})
print(dt)
"""
a b
0 0 3.0
1 1 4.0
2 2 NaN
"""
4.2.DataFrame的基本用法
4.2.1.T转置
在 pandas
中,.T
属性可以用来转置一个 DataFrame
。转置操作会将行和列进行互换。
import numpy as np
import pandas as pd
pd1 = pd.DataFrame(np.arange(9).reshape(3, 3), index=['a', 'b', 'c'], columns=['A', 'B', 'C'])
"""
A B C
a 0 1 2
b 3 4 5
c 6 7 8
"""
print("*****************T转置*****************")
print(pd1.T)
"""
a b c
A 0 3 6
B 1 4 7
C 2 5 8
"""
可以看到,转置后的 DataFrame 中,原来的行变成了列,原来的列变成了行。注意事项:
- 如果 DataFrame 的列和行标签都是唯一的,转置操作是非常直观的。
- 对于大型 DataFrame,转置操作可能会消耗较多内存和计算资源,因此需要根据实际情况评估性能。
4.2.2.通过列索引获取列数据(Series类型)
在 pandas
中,可以通过列索引来获取特定列的数据,返回的结果是一个 Series
类型。可以使用多种方法来实现这一点,包括使用中括号 []
、点符号 .
和 loc
/iloc
属性。下面是一些示例:
import numpy as np
import pandas as pd
pd1 = pd.DataFrame(np.arange(9).reshape(3, 3), index=['a', 'b', 'c'], columns=['A', 'B', 'C'])
"""
A B C
a 0 1 2
b 3 4 5
c 6 7 8
"""
# 方法 1: 使用中括号 []
column_A = pd1['A']
print(column_A)
"""
a 0
b 3
c 6
Name: A, dtype: int32
"""
print(type(column_A)) # <class 'pandas.core.series.Series'>
# 方法 2: 使用点符号 .
# 获取列 'B' 的数据
column_B = pd1.B
print(column_B)
"""
a 1
b 4
c 7
Name: B, dtype: int32
"""
print(type(column_B)) # <class 'pandas.core.series.Series'>
# 方法 3: 使用 loc 属性(上面index设置的索引就可以通过loc取值)
# 获取列 'C' 的数据
column_C = pd1.loc[:, 'C']
print(column_C)
"""
a 2
b 5
c 8
Name: C, dtype: int32
"""
print(type(column_C)) # <class 'pandas.core.series.Series'>
# 方法 4: 使用 iloc 属性 (通过列的索引位置)
# 获取第一列 (索引位置为 0) 的数据
column_0 = pd1.iloc[0]
print(column_0)
"""
A 0
B 1
C 2
Name: a, dtype: int32
"""
print(type(column_0)) # <class 'pandas.core.series.Series'>
在 pandas
中,使用 loc
属性时,冒号 :
有选择行或列的范围的作用。具体来说,冒号可以用于选择整个行或列。在 DataFrame
中,loc
属性的基本语法是 df.loc[row_selection, column_selection]
。冒号 :
的作用
- 在行选择中使用冒号
:
可以选择所有行。 - 在列选择中使用冒号
:
可以选择所有列。
4.2.3.增加列数据
在 pandas
中,可以通过多种方法向 DataFrame
中添加新列。下面是一些常用的方法:
方法 1: 直接赋值
通过直接赋值的方式增加新列:
import numpy as np
import pandas as pd
pd1 = pd.DataFrame(np.arange(9).reshape(3, 3), index=['a', 'b', 'c'], columns=['A', 'B', 'C'])
"""
A B C
a 0 1 2
b 3 4 5
c 6 7 8
"""
# 方法 1: 直接赋值
pd1['D'] = [9, 10, 11]
# 输出增加新列后的 DataFrame
print(pd1)
"""
A B C D
a 0 1 2 9
b 3 4 5 10
c 6 7 8 11
"""
方法 2: 使用 assign
方法
通过 assign
方法增加新列:
import numpy as np
import pandas as pd
pd1 = pd.DataFrame(np.arange(9).reshape(3, 3), index=['a', 'b', 'c'], columns=['A', 'B', 'C'])
"""
A B C
a 0 1 2
b 3 4 5
c 6 7 8
"""
# 增加新列 'E' 并创建新的 DataFrame
pd2 = pd1.assign(E=[12, 13, 14])
# 输出增加新列后的 DataFrame
print(pd2)
"""
A B C E
a 0 1 2 12
b 3 4 5 13
c 6 7 8 14
"""
方法 3: 使用 insert
方法
通过 insert
方法在特定位置插入新列:
import numpy as np
import pandas as pd
pd1 = pd.DataFrame(np.arange(9).reshape(3, 3), index=['a', 'b', 'c'], columns=['A', 'B', 'C'])
"""
A B C
a 0 1 2
b 3 4 5
c 6 7 8
"""
# 在索引位置 1 处插入新列 'F'
pd1.insert(1, "F", [12, 13, 14])
# 输出增加新列后的 DataFrame
print(pd1)
"""
A F B C
a 0 12 1 2
b 3 13 4 5
c 6 14 7 8
"""
方法 4: 根据现有列计算新列
根据现有列的数据计算新列:
import numpy as np
import pandas as pd
pd1 = pd.DataFrame(np.arange(9).reshape(3, 3), index=['a', 'b', 'c'], columns=['A', 'B', 'C'])
"""
A B C
a 0 1 2
b 3 4 5
c 6 7 8
"""
# 计算列 'G',其值为列 'A' 和列 'B' 之和
pd1['G'] = pd1['A'] + pd1['B']
# 输出增加新列后的 DataFrame
print(pd1)
"""
A B C G
a 0 1 2 1
b 3 4 5 7
c 6 7 8 13
"""
4.2.4.删除列
在 pandas
中,可以通过多种方法删除 DataFrame 中的列。下面介绍几种常用的方法:
方法 1: 使用 drop
方法
使用 drop
方法删除列:
import numpy as np
import pandas as pd
pd1 = pd.DataFrame(np.arange(9).reshape(3, 3), index=['a', 'b', 'c'], columns=['A', 'B', 'C'])
"""
A B C
a 0 1 2
b 3 4 5
c 6 7 8
"""
# 删除列 'B'
pd1_drop = pd1.drop(columns=['B'])
print(pd1_drop)
"""
A C
a 0 2
b 3 5
c 6 8
"""
方法 2: 使用 del
关键字
使用 del
关键字删除列:
import numpy as np
import pandas as pd
pd1 = pd.DataFrame(np.arange(9).reshape(3, 3), index=['a', 'b', 'c'], columns=['A', 'B', 'C'])
"""
A B C
a 0 1 2
b 3 4 5
c 6 7 8
"""
# 使用 del 删除列 'C'
del pd1['C']
print(pd1)
"""
A B
a 0 1
b 3 4
c 6 7
"""
方法 3: 使用 pop
方法
使用 pop
方法删除并返回指定列:
import numpy as np
import pandas as pd
pd1 = pd.DataFrame(np.arange(9).reshape(3, 3), index=['a', 'b', 'c'], columns=['A', 'B', 'C'])
"""
A B C
a 0 1 2
b 3 4 5
c 6 7 8
"""
# 使用 pop 删除并返回列 'A'
column_A = pd1.pop('A')
print(column_A)
"""
a 0
b 3
c 6
Name: A, dtype: int32
"""
print(pd1)
"""
B C
a 1 2
b 4 5
c 7 8
"""
方法 4: 使用索引方式
直接使用索引方式删除列:
import numpy as np
import pandas as pd
pd1 = pd.DataFrame(np.arange(9).reshape(3, 3), index=['a', 'b', 'c'], columns=['A', 'B', 'C'])
"""
A B C
a 0 1 2
b 3 4 5
c 6 7 8
"""
# 使用索引方式删除列 'B'
pd1 = pd1.drop(columns=['B'])
print(pd1)
"""
A C
a 0 2
b 3 5
c 6 8
"""
详细说明
- 使用
drop
方法:pd1.drop(columns=['B'])
删除列 'B' 并返回一个新的 DataFrame,原始 DataFrame 不变。 - 使用
del
关键字:del pd1['C']
直接从原始 DataFrame 中删除列 'C',原地操作,不返回新的 DataFrame。 - 使用
pop
方法:pd1.pop('A')
删除并返回列 'A',原地操作,同时返回被删除的列。 - 直接使用索引方式:
pd1 = pd1.drop(columns=['B'])
同样是使用drop
方法删除列 'B',但这里将结果重新赋值给原始 DataFrame。
4.3.DataFrame常用的属性
values、columns、index、shape用法和series差不多直接调用即可
-
values
:返回 DataFrame 的数据部分,二维 numpy 数组。 -
columns
:返回 DataFrame 的列标签,类型为 Index。 -
index
:返回 DataFrame 的行索引标签,类型为 Index。 -
shape
:返回 DataFrame 的维度信息,即行数和列数的元组。
import numpy as np
import pandas as pd
pd1 = pd.DataFrame(np.arange(9).reshape(3, 3), index=['a', 'b', 'c'], columns=['A', 'B', 'C'])
"""
A B C
a 0 1 2
b 3 4 5
c 6 7 8
"""
# 使用values:返回 DataFrame 的数据部分,二维 numpy 数组。
print(pd1.values)
"""
[[0 1 2]
[3 4 5]
[6 7 8]]
"""
# columns 属性返回 DataFrame 的列标签(列名)。
print(pd1.columns) # Index(['A', 'B', 'C'], dtype='object')
# index 属性返回 DataFrame 的行索引标签。
print(pd1.index) # Index(['a', 'b', 'c'], dtype='object')
# shape 属性返回 DataFrame 的维度信息,即行数和列数。
print(pd1.shape) # (3, 3)
4.4.DataFrame索引操作
4.4.1.对列进行索引
import numpy as np
import pandas as pd
pd1 = pd.DataFrame(data=np.random.randint(50, 100, size=(3, 4)), columns=['a', 'b', 'c', 'd'])
print(pd1)
"""
a b c d
0 55 73 64 62
1 67 75 60 54
2 71 95 87 51
"""
# 取单列,如果pd1有显示的索引,通过索引机制取行或者列的时候只可以使用显示索引
print(pd1['a'])
"""
0 55
1 67
2 71
Name: a, dtype: int32
"""
# 取多列
print(pd1[['a', 'c']])
"""
a c
0 55 64
1 67 60
2 71 87
"""
4.4.2.对行进行索引和对元素进行索引
- iloc:通过隐式索引取行
- loc:通过显示索引取行
import numpy as np
import pandas as pd
pd1 = pd.DataFrame(data=np.random.randint(50, 100, size=(3, 4)), columns=['a', 'b', 'c', 'd'])
print(pd1)
"""
a b c d
0 82 66 51 80
1 78 53 74 64
2 89 71 82 97
"""
# 取单行,这里的pd1行索引为隐式索引(没有指定索引),用iloc或loc都可以
print(pd1.iloc[0])
"""
a 82
b 66
c 51
d 80
Name: 0, dtype: int32
"""
# 取多行
print(pd1.iloc[[0, 2]]) # 取第0行和第2行
"""
a b c d
0 82 66 51 80
2 89 71 82 97
"""
# 取单个元素
print(pd1.iloc[0, 2]) # 取第0行第2列的元素 51
# 取多个元素
print(pd1.iloc[[0, 2], 2]) # 取第0行和第2行的第二列元素
"""
0 51
2 82
Name: c, dtype: int32
"""
4.5.DataFrame的切片操作
import numpy as np
import pandas as pd
pd1 = pd.DataFrame(data=np.random.randint(50, 100, size=(6, 4)), columns=['a', 'b', 'c', 'd'])
print(pd1)
"""
a b c d
0 95 57 67 62
1 58 81 59 79
2 81 80 66 69
3 51 73 69 50
4 54 75 58 60
5 78 56 96 63
"""
# 切行(切取索引0-3行下面两种方式结果相同)
print(pd1[0:4])
print(pd1.iloc[0:4])
"""
a b c d
0 95 57 67 62
1 58 81 59 79
2 81 80 66 69
3 51 73 69 50
"""
# 切列
print(pd1.iloc[:, 0:2])
"""
a b
0 95 57
1 58 81
2 81 80
3 51 73
4 54 75
5 78 56
"""
DataFrame索引和切片操作:
⑴.索引:
df[col]:取列
df.loc[index]:取行
df.iloc[index,col]:取元素
⑵.切片:
df[index1:index3]:切行
df.iloc[:,col1:col3]:切列